dsh-plugin-lcu 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +23 -19
- package/cordis.patch.yml +1 -0
- package/docs/README.zh.md +17 -14
- package/lib/bridge.js +72 -0
- package/lib/bridge.js.map +1 -0
- package/lib/connection.js +3 -3
- package/lib/index.js +9 -8
- package/lib/index.js.map +1 -1
- package/lib/ptc.js +372 -0
- package/lib/ptc.js.map +1 -0
- package/lib/tool.js +5 -8
- package/lib/tool.js.map +1 -1
- package/lib/types/bridge.d.ts +38 -0
- package/lib/types/bridge.d.ts.map +1 -0
- package/lib/types/connection.d.ts +3 -3
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/ptc.d.ts +85 -0
- package/lib/types/ptc.d.ts.map +1 -0
- package/lib/types/tool.d.ts +18 -8
- package/lib/types/tool.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/codex-baseline.json +3 -3
- package/scripts/update-codex.mjs +21 -5
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PTC-facing LCU surface.
|
|
3
|
+
*
|
|
4
|
+
* The ChatGPT application's CUA runtime is a JavaScript REPL (`js`). PTC
|
|
5
|
+
* programs cannot call that REPL's `cua` object directly, so this module exposes
|
|
6
|
+
* one ordinary tool, `cua`, whose binding is a small RPC: a program calls a
|
|
7
|
+
* method, the host runs it inside the persistent CUA REPL, and app/tab/window
|
|
8
|
+
* objects come back as opaque handles.
|
|
9
|
+
*
|
|
10
|
+
* The model never sees the `js` tool. It sees the generated SDK's `tools.cua`
|
|
11
|
+
* binding and the `connectCua` prelude in {@link ptcBridgeInstructions}.
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-plugin-lcu/ptc
|
|
14
|
+
*/
|
|
15
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
16
|
+
import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
|
|
17
|
+
import type { RuntimeConnection } from './session.ts';
|
|
18
|
+
/** The single model-facing tool of the PTC surface. */
|
|
19
|
+
export declare const CUA_TOOL_NAME = "cua";
|
|
20
|
+
/** Marker printed by the in-REPL bridge so the host can find structured output. */
|
|
21
|
+
export declare const CUA_RESULT_MARKER = "__DSH_LCU_RESULT__";
|
|
22
|
+
/**
|
|
23
|
+
* The in-REPL half of the bridge.
|
|
24
|
+
*
|
|
25
|
+
* It is deliberately installed with `??=` so a persistent PTC runtime (or a
|
|
26
|
+
* persistent CUA REPL) can call it many times without replacing live handles.
|
|
27
|
+
* Values that expose methods are remembered and returned as opaque handles;
|
|
28
|
+
* plain JSON is passed through unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CUA_PRELUDE: string;
|
|
31
|
+
/** Host-owned hooks around one bridge call. */
|
|
32
|
+
export interface CuaToolOptions {
|
|
33
|
+
/** Awaited before every call; a rejection fails the call. */
|
|
34
|
+
readonly beforeCall?: () => Promise<void>;
|
|
35
|
+
/** The Agent's active turn identity, used for runtime approvals and cleanup. */
|
|
36
|
+
readonly currentTurn?: () => string | undefined;
|
|
37
|
+
}
|
|
38
|
+
/** One validated bridge request. */
|
|
39
|
+
export interface CuaRequest {
|
|
40
|
+
readonly target?: string;
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly args: readonly unknown[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate the model's arguments.
|
|
46
|
+
*
|
|
47
|
+
* The tool is intentionally generic; the method name and positional arguments
|
|
48
|
+
* are checked here so the in-REPL bridge never receives a non-string method or
|
|
49
|
+
* a non-array argument list.
|
|
50
|
+
*
|
|
51
|
+
* @param value - parsed tool arguments.
|
|
52
|
+
* @returns the normalized request.
|
|
53
|
+
* @throws {Error} when the request shape is not usable.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readCuaRequest(value: unknown): CuaRequest;
|
|
56
|
+
/**
|
|
57
|
+
* Build the one model-facing PTC tool.
|
|
58
|
+
*
|
|
59
|
+
* @param connection - the Agent's LCU connection.
|
|
60
|
+
* @param ctx - the plugin context, kept for the screenshot/attachment projection.
|
|
61
|
+
* @param options - host hooks.
|
|
62
|
+
* @returns a registrable tool definition.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createCuaTool(connection: RuntimeConnection, ctx: Context, options?: CuaToolOptions): ToolDefinition;
|
|
65
|
+
/**
|
|
66
|
+
* Register the PTC surface in one Agent's scope.
|
|
67
|
+
*
|
|
68
|
+
* @param agentCtx - the Agent's own context; registrations unwind on disposal.
|
|
69
|
+
* @param connection - the Agent's connected LCU session.
|
|
70
|
+
* @param ctx - the plugin context.
|
|
71
|
+
* @param options - host hooks.
|
|
72
|
+
* @returns a disposer that unregisters the tool.
|
|
73
|
+
*/
|
|
74
|
+
export declare function registerCuaTool(agentCtx: Context, connection: RuntimeConnection, ctx: Context, options?: CuaToolOptions): () => void;
|
|
75
|
+
/**
|
|
76
|
+
* Model-facing PTC instructions.
|
|
77
|
+
*
|
|
78
|
+
* The generated SDK already declares `tools.cua`; this section teaches the model
|
|
79
|
+
* how to turn it into the same `cua` object the native REPL used to expose.
|
|
80
|
+
*
|
|
81
|
+
* @param bridgeUrl - absolute `file:` URL of the compiled `bridge.js`.
|
|
82
|
+
* @returns the prompt section text.
|
|
83
|
+
*/
|
|
84
|
+
export declare function ptcBridgeInstructions(bridgeUrl: string): string;
|
|
85
|
+
//# sourceMappingURL=ptc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ptc.d.ts","sourceRoot":"","sources":["../../src/ptc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAE,cAAc,EAAsD,MAAM,wBAAwB,CAAA;AAGhH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAGrD,uDAAuD;AACvD,eAAO,MAAM,aAAa,QAAQ,CAAA;AAElC,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,uBAAuB,CAAA;AASrD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,QAyDvB,CAAA;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC,gFAAgF;IAChF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;CAChD;AAED,oCAAoC;AACpC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;CAClC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAiBzD;AAqHD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,cAAmB,GAC3B,cAAc,CAqFhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,IAAI,CAEZ;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAwB/D"}
|
package/lib/types/tool.d.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Model-facing tools for LCU.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* unchanged — this module only adapts the transport (canonical value, text
|
|
8
|
-
* fallback, durable images) and enforces the visibility rule that only `js` and
|
|
9
|
-
* `js_reset` may reach the model.
|
|
4
|
+
* These builders predate the PTC surface and remain for the internal `js`
|
|
5
|
+
* transport plus the tests that cover it. The model-facing registration in
|
|
6
|
+
* `index.ts` now uses `ptc.ts`: PTC programs see `cua`, never `js`.
|
|
10
7
|
*
|
|
11
8
|
* @module dsh-plugin-lcu/tool
|
|
12
9
|
*/
|
|
13
10
|
import type { Context } from '@deepseek-ai/cordis';
|
|
14
|
-
import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
|
|
11
|
+
import type { ToolDefinition, ToolRunContext } from '@deepseek-ai/dsh-tools';
|
|
15
12
|
import type { LcuContentBlock, LcuTool } from './connection.ts';
|
|
16
13
|
import type { RuntimeConnection } from './session.ts';
|
|
17
14
|
interface ImageBlock {
|
|
@@ -19,6 +16,13 @@ interface ImageBlock {
|
|
|
19
16
|
readonly data: string;
|
|
20
17
|
readonly mimeType: string;
|
|
21
18
|
}
|
|
19
|
+
interface PreparedProjection {
|
|
20
|
+
readonly value: unknown;
|
|
21
|
+
readonly content: readonly {
|
|
22
|
+
readonly type: string;
|
|
23
|
+
readonly [key: string]: unknown;
|
|
24
|
+
}[];
|
|
25
|
+
}
|
|
22
26
|
/**
|
|
23
27
|
* The model-facing text for one MCP result.
|
|
24
28
|
*
|
|
@@ -44,6 +48,12 @@ export declare function decodeImage(block: ImageBlock): {
|
|
|
44
48
|
};
|
|
45
49
|
/** Stable diagnostic text for an image the host could not admit. */
|
|
46
50
|
export declare function imageDiagnostic(block: unknown, reason: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Build the ordered content blocks for one result: text and images interleaved
|
|
53
|
+
* exactly as the server emitted them, with any inadmissible image replaced by a
|
|
54
|
+
* diagnostic instead of failing the whole call.
|
|
55
|
+
*/
|
|
56
|
+
export declare function prepareProjection(ctx: Context, exec: ToolRunContext, content: readonly LcuContentBlock[], toolName: string): Promise<PreparedProjection['content']>;
|
|
47
57
|
/** Host-owned hooks around one call. */
|
|
48
58
|
export interface LcuToolOptions {
|
|
49
59
|
/**
|
|
@@ -99,7 +109,7 @@ export declare function stuckStopHint(text: string): string | undefined;
|
|
|
99
109
|
*/
|
|
100
110
|
export declare function createLcuTool(descriptor: LcuTool, connection: RuntimeConnection, ctx: Context, options?: LcuToolOptions): ToolDefinition;
|
|
101
111
|
/**
|
|
102
|
-
* Build
|
|
112
|
+
* Build the legacy native tools for one agent's connection.
|
|
103
113
|
*
|
|
104
114
|
* @param connection - the connected LCU session.
|
|
105
115
|
* @param ctx - the plugin context.
|
package/lib/types/tool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/tool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,cAAc,EAAsC,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEhH,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAUrD,UAAU,UAAU;IAClB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,EAAE,CAAA;CACxF;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWzF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAQlF;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAiCD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CA8DxC;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;CAChD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAO5E;AAWD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWtE;AAcD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,cAAmB,GAC3B,cAAc,CA+DhB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,cAAmB,GAC3B,cAAc,EAAE,CAOlB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,iBAAiB,EAC7B,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,GACpC,cAAc,CAsEhB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,IAAI,CASZ"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-lcu",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "PTC Computer/Browser CUA for DeepSeek Harness, backed by the runtime inside the ChatGPT desktop application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh-plugin",
|
|
7
7
|
"deepseek-harness",
|
package/scripts/update-codex.mjs
CHANGED
|
@@ -55,7 +55,16 @@ const CODEX_ENTRY = 'node_modules/@openai/codex/bin/codex.js'
|
|
|
55
55
|
// fetch every OS/arch payload (~275 MB each).
|
|
56
56
|
const OVERRIDE_KEY = '"@deepseek-ai/dsh-subagent-codex>@openai/codex"'
|
|
57
57
|
const OVERRIDE_RE = /^\s*"@deepseek-ai\/dsh-subagent-codex>@openai\/codex":.*$/m
|
|
58
|
-
|
|
58
|
+
// The Desktop app bundles the pnpm the profile was installed with, and that
|
|
59
|
+
// payload moves between releases: 0.2.1-rc.3 keeps it under primary-runtime,
|
|
60
|
+
// while older builds used runtime/pnpm. Resolve the first one that exists —
|
|
61
|
+
// a PATH pnpm is only a last resort, because a different pnpm may refuse this
|
|
62
|
+
// profile's node_modules without a TTY.
|
|
63
|
+
const APP_PNPM_CANDIDATES = [
|
|
64
|
+
'/Applications/DeepSeek Harness.app/Contents/Resources/runtime/primary-runtime/dependencies/pnpm/bin/pnpm.mjs',
|
|
65
|
+
'/Applications/DeepSeek Harness.app/Contents/Resources/runtime/pnpm/bin/pnpm.cjs',
|
|
66
|
+
]
|
|
67
|
+
const APP_PNPM = APP_PNPM_CANDIDATES.find((path) => existsSync(path))
|
|
59
68
|
|
|
60
69
|
/**
|
|
61
70
|
* The protocol surface dsh-subagent-codex/src/wire.ts actually uses.
|
|
@@ -129,7 +138,11 @@ function readOverride(text) {
|
|
|
129
138
|
function writeOverride(text, version, key = OVERRIDE_KEY) {
|
|
130
139
|
const line = ` ${key}: "${version}"`
|
|
131
140
|
if (OVERRIDE_RE.test(text)) {
|
|
132
|
-
|
|
141
|
+
// Keep the two-space indent: the replacement line lands inside the
|
|
142
|
+
// `overrides:` mapping. Dropping it (a previous bug) turned the key into a
|
|
143
|
+
// top-level entry, so pnpm silently ignored the override and installed the
|
|
144
|
+
// dependency's own pin instead.
|
|
145
|
+
return text.replace(OVERRIDE_RE, line)
|
|
133
146
|
}
|
|
134
147
|
if (/^overrides:/m.test(text)) {
|
|
135
148
|
return text.replace(/^overrides:\s*$/m, `overrides:\n${line}`)
|
|
@@ -399,12 +412,15 @@ function install(profile, runner) {
|
|
|
399
412
|
env: { ...process.env, CI: 'true' },
|
|
400
413
|
})
|
|
401
414
|
if (result.status !== 0) {
|
|
402
|
-
|
|
415
|
+
// spawnSync reports a failure to start (missing executable, EACCES) as a
|
|
416
|
+
// null status plus `error`; without it the message would be empty.
|
|
417
|
+
const spawnFailure = result.error === undefined ? '' : `${result.error.message}\n`
|
|
418
|
+
const detail = `${spawnFailure}${result.stdout ?? ''}\n${result.stderr ?? ''}`
|
|
403
419
|
.split('\n')
|
|
404
420
|
.filter((line) => line.trim() !== '' && !line.includes('NPM_TOKEN'))
|
|
405
421
|
.slice(-25)
|
|
406
422
|
.join('\n')
|
|
407
|
-
throw new Error(`pnpm install failed (${result.status}):\n${detail}`)
|
|
423
|
+
throw new Error(`pnpm install failed (${String(result.status)}):\n${detail}`)
|
|
408
424
|
}
|
|
409
425
|
}
|
|
410
426
|
|
|
@@ -417,7 +433,7 @@ function install(profile, runner) {
|
|
|
417
433
|
*/
|
|
418
434
|
function resolvePnpm(explicit) {
|
|
419
435
|
if (explicit !== undefined) return [explicit]
|
|
420
|
-
if (
|
|
436
|
+
if (APP_PNPM !== undefined) return [process.execPath, APP_PNPM]
|
|
421
437
|
return ['pnpm']
|
|
422
438
|
}
|
|
423
439
|
|