Implement extensions/vision/src/tool.ts (the vision ToolDefinition) #258
Closed
opened 2026-09-17 03:34:09 +00:00 by david
·
1 comment
No Branch/Tag specified
main
feature/issue-342/mssql-write-access-check-and-startup-warning-never
feature/issue-331/mssql-write-extensions-mssql-readme-md-setup-tools
feature/issue-330/mssql-register-extension-add-tests-to-root-test-sc
feature/issue-329/mssql-index-ts-wiring-load-env-refuse-on-invalid-l
feature/issue-328/mssql-mssql-table-schema-tool-parameterised
feature/issue-327/mssql-mssql-list-tables-tool
feature/issue-326/mssql-mssql-query-and-mssql-query-one-tools
feature/issue-325/mssql-stream-runner-with-row-cap-cancel-and-timeou
feature/issue-324/mssql-pool-config-builder-encrypt-on-certificate-s
feature/issue-323/mssql-audit-log-writer-pi-mssql-audit-log-mode-060
feature/issue-322/mssql-read-only-guard-module-validatesql-with-corp
feature/issue-321/mssql-certificate-trust-setting-and-limit-validati
feature/issue-320/mssql-loadenvfile-and-mssql-url-parsing
feature/issue-319/mssql-extension-skeleton-permanent-corpora-and-dep
feature/issue-318/mssql-spike-write-result-md-apply-the-gate-open-th
feature/issue-317/mssql-spike-scoring-runner-for-both-candidates
feature/issue-316/mssql-spike-candidate-b-guard-using-the-antlr4-t-s
feature/issue-315/mssql-spike-candidate-a-guard-using-node-sql-parse
feature/issue-314/mssql-spike-must-accept-corpus
feature/issue-313/mssql-spike-scaffold-spike-directory-and-must-reje
feature/issue-311/mssql-spike-check-dependencies-mssql-node-sql-pars
feature/issue-312/mssql-spike-check-whether-extension-tests-run-in-c
feature/issue-299/verify-the-ste-style-live-in-a-short-grill-session
feature/issue-298/bump-the-grillme-extension-to-0-4-0-and-add-the-ch
feature/issue-297/rewrite-extensions-grillme-design-md-in-ste-style
feature/issue-296/rewrite-extensions-grillme-readme-md-in-ste-style
feature/issue-295/rewrite-the-grill-me-command-output-and-read-only
feature/issue-294/rewrite-the-grill-me-tool-metadata-to-the-ste-rule
feature/issue-293/extract-buildgrillprompt-and-add-the-prompt-integr
feature/issue-292/add-ste-style-test-ts-checks-for-the-rule-text-and
feature/issue-291/add-the-pure-ste-style-ts-module-and-inject-the-st
feature/issue-264/verify-the-vision-tool-live-against-the-deepseek-a
feature/issue-263/list-the-vision-extension-in-the-repo-root-readme
feature/issue-262/write-extensions-vision-readme-md-the-10-section-p
feature/issue-261/wire-the-vision-extension-into-package-json-manife
feature/issue-260/implement-extensions-vision-index-ts-factory-regis
feature/issue-258/implement-extensions-vision-src-tool-ts-the-vision
feature/issue-257/implement-extensions-vision-src-client-ts-request
feature/issue-256/implement-extensions-vision-src-usage-ts-usage-map
feature/issue-255/implement-extensions-vision-src-images-ts-read-val
feature/issue-254/implement-extensions-vision-src-config-ts-env-reso
feature/issue-253/implement-extensions-vision-src-errors-ts-toolerro
feature/issue-252/penpot-add-text-stages-zero-area-auto-width-text-p
feature/issue-216/add-the-penpot-skill-and-extension-to-the-repo-roo
feature/issue-217/register-the-penpot-tests-in-npm-test-complete-the
feature/issue-215/write-the-penpot-skill-md-core-workflow-token-conv
feature/issue-214/implement-and-run-fetch-penpot-docs-mjs-and-commit
feature/issue-213/validate-screenshot-reconstruction-against-the-liv
feature/issue-212/add-the-image-to-design-workflow-to-skills-penpot
feature/issue-211/validate-svg-import-icon-and-illustration-against
feature/issue-210/implement-the-penpot-add-svg-tool-with-svg-raw-fal
feature/issue-209/implement-the-svg-to-shapes-converter-in-src-svg-t
feature/issue-208/validate-component-instancing-against-the-live-ins
feature/issue-207/implement-penpot-instance-component-with-id-remapp
feature/issue-206/author-and-commit-the-component-library-artifact-u
feature/issue-205/implement-file-library-linking-and-validate-the-ex
feature/issue-204/implement-penpot-export-library-sse-uri-plus-artif
feature/issue-203/implement-penpot-import-library-multipart-upload-p
feature/issue-202/implement-the-transit-decoder-and-sse-stream-parse
feature/issue-201/validate-a-full-composed-screen-one-commit-one-rev
feature/issue-200/implement-penpot-add-image-with-media-upload
feature/issue-199/implement-asset-reference-resolution-plus-penpot-a
feature/issue-198/implement-penpot-add-frame-with-auto-layout-props
feature/issue-197/validate-asset-creation-atomicity-and-write-safety
feature/issue-196/implement-the-designated-target-write-guard-with-a
feature/issue-195/implement-penpot-commit-with-revn-tracking-conflic
feature/issue-194/implement-the-staged-changeset-store-and-the-colou
feature/issue-193/validate-read-primitives-against-the-live-penpot-i
feature/issue-192/implement-the-penpot-list-library-tool-with-name-t
feature/issue-191/implement-the-penpot-get-file-tool-pages-objects-a
feature/issue-190/implement-the-penpot-list-projects-tool-teams-and
feature/issue-189/implement-the-penpot-whoami-tool-and-wire-the-exte
feature/issue-188/implement-the-rpc-client-and-error-decoding-in-src
feature/issue-187/implement-penpot-url-penpot-token-resolution-in-sr
feature/issue-186/scaffold-the-penpot-extension-directory-and-regist
feature/issue-172/add-end-to-end-main-tests-for-the-fj-rg-tool-state
feature/issue-171/make-reminder-report-dynamic-install-skip-counts-r
feature/issue-170/wire-settings-json-filter-rewrite-into-dedupeandre
feature/issue-169/implement-buildpackagefilters-with-exhaustive-unit
feature/issue-168/refactor-preflight-to-skip-warn-for-missing-fj-rg
feature/issue-167/add-fj-rg-tool-detection-helpers-rgavailable-detec
feature/issue-148/reconcile-design-md-and-implementation-plan-with-t
feature/issue-146/verify-extension-load-behavior-with-and-without-mo
feature/issue-145/write-extensions-mongodb-readme-md
feature/issue-144/write-tool-description-promptsnippet-guidance-for
feature/issue-143/implement-index-ts-async-factory-lifecycle-with-te
feature/issue-142/implement-the-mongo-list-collections-tool-with-uni
feature/issue-141/implement-the-mongo-count-tool-with-unit-tests
feature/issue-140/implement-the-mongo-find-tool-with-unit-tests
feature/issue-139/implement-src-errors-ts-with-unit-tests-toolerror
feature/issue-138/implement-src-serialize-ts-with-unit-tests-ejson-t
feature/issue-136/implement-src-env-ts-with-unit-tests-mongodb-uri-r
feature/issue-135/register-the-mongodb-extension-in-the-repo-root-pa
feature/issue-133/initialize-the-extensions-mongodb-package-package
feature/issue-116/src-actions-ts-downloadrunlogs-zip-guarded-unzip-c
feature/issue-115/src-actions-ts-downloadjoblog-cache-first-attempt
feature/issue-114/src-actions-ts-metadata-queries-listactionruns-get
feature/issue-113/src-actionscache-ts-cache-paths-cache-first-read-w
feature/issue-112/add-zip-extraction-dependency-adm-zip-vs-yauzl
feature/issue-111/tracking-forgejo-actions-tooling-read-only-runs-jo
feature/issue-93/add-unit-tests-for-scripts-local-install-mjs-node
feature/issue-92/validate-install-local-end-to-end-on-the-dev-machi
feature/issue-90/implement-pi-registration-with-url-dedupe-and-relo
feature/issue-89/validate-install-local-from-a-scratch-clone-fresh
feature/issue-88/implement-git-pull-and-npm-install-steps-in-script
feature/issue-74/write-victorialogs-readme-md-and-reconcile-design
feature/issue-73/wire-up-index-ts-extension-factory-and-register-al
feature/issue-72/implement-logs-facets-tool-src-tools-facets-ts
feature/issue-71/implement-logs-hits-tool-src-tools-hits-ts
feature/issue-70/implement-logs-search-tool-src-tools-search-ts
feature/issue-69/implement-parsejsonlines-helper-in-src-client-ts
feature/issue-68/implement-victorialogsrequest-in-src-client-ts
feature/issue-67/implement-resolvebaseurl-in-src-env-ts
feature/issue-66/implement-totoolerror-in-src-errors-ts
feature/issue-65/implement-src-defaults-ts-shared-constants-and-app
feature/issue-64/scaffold-the-victorialogs-pi-extension-project
feature/issue-53/skip-issue-creation-for-chore-documentation-commit
feature/issue-45/fix-local-install-preflight-env-var-requirements-s
feature/issue-41/add-npm-run-local-install-script-to-update-and-ins
feature/issue-26/cross-reference-forgejo-list-milestones-from-issue
feature/issue-25/add-forgejo-milestone-delete-tool
feature/issue-24/add-forgejo-milestone-close-and-forgejo-milestone
feature/issue-23/add-forgejo-milestone-edit-tool
feature/issue-22/add-forgejo-milestone-view-tool
feature/issue-21/add-forgejo-list-milestones-tool
feature/issue-20/add-forgejo-milestone-create-tool
feature/issue-18/add-forgejo-label-create-tool
feature/issue-29/bug-forgejo-issue-create-view-edit-close-etc-crash
No results found.
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills#258
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Create
extensions/vision/src/tool.ts: thevisiontool definition — its TypeBox parameter schema, name/label/description, prompt metadata, and theexecute()that validates images, calls the client, maps usage, and handles the response edge cases.Background
Depends on: #253, #255, #256, #257
This is the module the LLM actually sees. It owns three things that the lower layers deliberately do not:
prompt,images, optionaldetail, optionalthinking— plus the prompt metadata (description,promptSnippet,promptGuidelines) that tells the model when to reach for this tool.promptGuidelinesbullets are appended flat to pi's guidelines with no tool-name prefix, so each bullet must namevisionexplicitly (pinned pi docs).thinkingvalue (per-call param, elseconfig.defaultThinking), validate images againstctx.cwd, build the body, call the client, map usage, and shapedetails.contentempty) must not silently return an empty string to the LLM.Every failure must be thrown as a
ToolError; a rawErrorfrom a lower layer still needs to be wrapped by a finalcatchin categoryunexpected. pi marks a tool failed only whenexecute()throws.StringEnumis deliberately not used: this repo's precedent isType.Union([Type.Literal(...)])(seeextensions/forgejo/src/index.ts), and the plan pins that choice.Documentation Required
A separate process downloads these into the listed folders before this issue is implemented. Check the folder for the actual reference material before starting.
docs/reference/pi-coding-agent/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md— theToolDefinitioncontract:name/label/description/parameters/execute(toolCallId, params, signal, onUpdate, ctx),promptSnippet,promptGuidelines, the flat-guidelines rule ("Each guideline must name the tool it refers to"), the return shape (content,details,usage), and "Signaling errors" (throw to fail).usagereturned fromexecuteis persisted on the tool result.docs/reference/typebox/Type.Object,Type.String,Type.Array,Type.Optional,Type.Union,Type.Literal, andType.Staticfor the inferred params type. This is thetypeboxv1 package (sinclairzx81) already inpackage.json; import from"typebox"like the other extensions do.docs/reference/deepseek-api/choices[0].message.content,reasoning_content,finish_reason, and theusagefields.Implementation Details
Public surface:
Parameters (
Type.Object, repo precedentType.Union([Type.Literal(...)])):Definition metadata:
name: "vision",label: "Vision".description: names the tool, states it sends local images todeepseek-flashand returns text, and says to use it when the current model cannot read an image.promptSnippet: "Read or analyze local image files with DeepSeek vision".promptGuidelines: an explicit bullet beginning "Use vision when …" that names the tool (guidelines are un-prefixed).execute(toolCallId, params, signal, onUpdate, ctx):thinking=params.thinking ?? config.defaultThinking;await loadAndValidateImages(params.images, ctx.cwd);buildRequestBody({ prompt, images, detail: params.detail, thinking }, config);await client.complete(body, signal)(pi may passsignal: undefined; the client still applies the deadline);mapUsage(response.usage);{ content: [{ type: "text", text }], details, usage }.Response handling (order matters):
message.content⇒ return it.contentwithfinish_reason === "length"⇒ToolError(response) whose message mentionsVISION_MAX_TOKENSand that reasoning tokens count toward the cap when thinking is on.contentotherwise ⇒ToolError(response) mentioning that the model may have returned only reasoning and the call can be retried withthinking: true.reasoning_contentis discarded (never returned to the LLM).executebody in atry/catch: re-throw aToolErrorunchanged, wrap anything else innew ToolError(..., "unexpected"). No raw stack trace reaches the model.detailsis populated for every successful call:model, effectivethinking,detail(only when supplied), the per-image metadata (path/mime/width/height/bytes, no data URL),durationMs(measure around the client call or the whole execute — pick one and document it), andfinishReason.Test file
extensions/vision/src/tool.test.ts(TDD, fakeVisionClient— never the network):vision.details+ mappedusagethrough a fake client;details.thinkingreflects the param and, when the param is omitted,config.defaultThinking.ToolErrorwithcategory === "image"and the client is never called.ToolError(response).finish_reason: "length"with empty content ⇒ToolErrormentioningVISION_MAX_TOKENS.ToolError(aborted) without leaking a raw error.ToolError(unexpected).Acceptance Criteria
vision/Visionwith a description,promptSnippet, and apromptGuidelinesbullet that names the tool.prompt, a non-emptyimagesarray, and optionaldetail/thinkingwith the documented descriptions.executeresolvesthinkingfrom the param withconfig.defaultThinkingas the fallback and passes it through to the request body.details(model, thinking, detail, per-image metadata, durationMs, finishReason) and a mappedusage.finish_reason: "length"raises aToolErrornamingVISION_MAX_TOKENS; empty content otherwise raises aresponseToolError.ToolError, including theunexpectedwrapper;reasoning_contentnever reaches the LLM.extensions/vision/src/tool.test.tspasses withnode --test extensions/vision/src/tool.test.tsand uses only a fake client.Test Plan
Expected: all tests pass with no network access and no real image files required beyond temp fixtures.
Manual shape inspection (no network — uses a fake client):
Expected:
vision Vision [ 'prompt', 'images', 'detail', 'thinking' ].pi-loop opened and merged a pull request for this issue: #272