Implement extensions/vision/index.ts (factory, registration, unconfigured no-op) #260
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills#260
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/index.ts: the extension's default-export factory. It loads.env+process.env, resolves the config, and either registers thevisiontool or logs a notice and registers nothing whenDEEPSEEK_API_KEYis absent. It also exports aregisterVisionToolsseam and acreateClientinjection point for tests.Background
Depends on: #254, #257, #258
pi loads an extension by importing its file and calling the default export with the
ExtensionAPIand any package options (pinned pi docs,docs/extensions.md). Everything below this file is pure library code with injected dependencies; this module is where the real environment meets them.The unconfigured path is a hard requirement: with no key,
pi.registerToolmust never be called, so a user without DeepSeek credentials gets a clean pi boot and no phantom tool. This mirrorsextensions/mongodb/index.ts, which returns early and registers nothing whenMONGODB_URIis missing.The test seam follows the repo's established shape:
registerVisionTools(pi, client, config)is exported soindex.test.tscan drive registration with a fakeExtensionAPIand a fake client, andoptions.createClientlets the factory's own wiring be exercised without a live HTTP client.There is no
session_shutdownwork to do — each call is a stateless read-only request that writes nothing.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— the default-export extension signature(pi: ExtensionAPI, options?) => void | Promise<void>,ExtensionAPI.registerTool, and an example of an extension factory that conditionally registers tools.node_modules/@earendil-works/pi-coding-agent/dist/**/*.d.ts— theExtensionAPIandToolDefinitiontypes to import.docs/reference/deepseek-api/deepseek-flash/https://api.deepseek.comas defaults (referenced fromconfig.ts).Implementation Details
Public surface:
Factory behaviour:
const env = { ...loadEnvFile(), ...process.env };const config = resolveConfig(env);configisnull:console.log("vision extension: DEEPSEEK_API_KEY not set — vision tool not registered.")andreturn;— no tool, no client, no throw.const client = options.createClient ? options.createClient(config) : createHttpVisionClient(config);thenregisterVisionTools(pi, client, config);.registerVisionToolscalls exactlypi.registerTool(visionTool(client, config))— one registration per call.Notes:
resolveConfigmay throw aToolError(config) for an invalid numeric env var. Let it propagate — that is intentional fail-loud-at-load behaviour and is the factory's documented contract; do not swallow it.session_shutdownhandling: nothing is opened or held.extensions/mongodb/index.tsfor doc-comment style and theregister*Toolsseam.Test file
extensions/vision/index.test.ts(TDD, fakepiobject, no network):registerToolis never called, and the notice is logged (captureconsole.log).registerToolcall and the registered definition'sname === "vision".options.createClientis honoured: the injected factory receives the resolvedconfigand its returned client is the one passed toregisterVisionTools.registerVisionToolsregisters exactly one tool with the supplied client/config.VISION_MAX_TOKENSin the env ⇒ the factory rejects with aToolErrorwhose category isconfig(proves config errors are not swallowed).Acceptance Criteria
pi.registerTool.nameisvision.options.createClient, when supplied, is used instead of the real HTTP client and receives the resolved config.registerVisionTools(pi, client, config)is exported and registers exactly one tool.ToolErrors propagate out of the factory rather than being swallowed.extensions/vision/index.test.tspasses withnode --test extensions/vision/index.test.tsand makes no network calls.Test Plan
Expected: all tests pass with no network access.
Manual unconfigured boot check (the repo root has no
DEEPSEEK_API_KEYby assumption):Expected: the unconfigured notice is logged and
registered: [].pi-loop opened and merged a pull request for this issue: #273