better-dsh 0.2.3-b → 0.2.3-d
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/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
- package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
- package/eval-description.md +33 -0
- package/lib/client/index.js +59 -50
- package/lib/index.d.ts +4 -21
- package/lib/index.js +37 -77
- package/lib/py-sdk-Chvy92MB.js +178 -0
- package/lib/py-sdk.d.ts +19 -2
- package/lib/py-sdk.js +2 -2
- package/package.json +3 -3
- package/control-prompt.md +0 -37
- package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
- package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
- package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
- package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
- package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
- package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
- package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
- package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
- package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
- package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
- package/docs/60_exploration-and-research/01-cordis-runtime/bun-compile-cordis-runtime-bootstrap-research.md +0 -536
- package/docs/60_exploration-and-research/01-cordis-runtime/cordis-customization-and-override-mechanics.md +0 -418
- package/docs/60_exploration-and-research/01-cordis-runtime/cordis-engineering-feasibility.md +0 -155
- package/docs/60_exploration-and-research/01-cordis-runtime/cordis-research.md +0 -583
- package/docs/60_exploration-and-research/01-cordis-runtime/dsh-cordis-hotplug-mcp-patch-research.md +0 -265
- package/docs/60_exploration-and-research/01-cordis-runtime/js-ts-language-fundamentals.md +0 -628
- package/docs/60_exploration-and-research/02-dsh/dash-research.md +0 -592
- package/docs/60_exploration-and-research/02-dsh/dsh-web-profile-package-map.md +0 -186
- package/docs/60_exploration-and-research/02-dsh/dsh-web-ui-slot-system-research.md +0 -310
- package/docs/60_exploration-and-research/02-dsh/dsh-webui-backend-data-inventory.md +0 -633
- package/docs/60_exploration-and-research/02-dsh/dsh-webui-strip-boundary-research.md +0 -300
- package/docs/60_exploration-and-research/02-dsh/dsh-webui-wire-appendix.md +0 -3729
- package/docs/60_exploration-and-research/02-dsh/web-frontend-composability-research.md +0 -191
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/capture-live-turn.json +0 -1
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/observed-endpoints.json +0 -224
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/remote-inventory.json +0 -110954
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/served-index-sample.html +0 -47
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/session-events.json +0 -9411
- package/docs/60_exploration-and-research/02-dsh/webui-wire-data/ws-frame-examples.json +0 -20
- package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-profile-package-map.md +0 -186
- package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-ui-slot-system-research.md +0 -310
- package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-backend-data-inventory.md +0 -633
- package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-strip-boundary-research.md +0 -300
- package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-wire-appendix.md +0 -3729
- package/docs/60_exploration-and-research/02-dsh-webui/web-frontend-composability-research.md +0 -191
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/capture-live-turn.json +0 -1
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/observed-endpoints.json +0 -224
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/remote-inventory.json +0 -110954
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/served-index-sample.html +0 -47
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/session-events.json +0 -9411
- package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/ws-frame-examples.json +0 -20
- package/docs/60_exploration-and-research/03-mobile-ios/dsh-mobile-spa-ios-input-experience-research.md +0 -160
- package/docs/60_exploration-and-research/03-mobile-ios/ios-chat-app-bridge-research.md +0 -324
- package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-jsonl-mapping.md +0 -1532
- package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode-failed.json +0 -46
- package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode1.json +0 -1124
- package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode2.json +0 -1240
- package/docs/60_exploration-and-research/05-dashr-dev/plugin-development.md +0 -148
- package/docs/60_exploration-and-research/05-dashr-dev/upstream-alignment.md +0 -102
- package/docs/60_exploration-and-research/README.md +0 -87
- package/docs/60_exploration-and-research/bun-compile-cordis-runtime-bootstrap-research.md +0 -348
- package/docs/60_exploration-and-research/cordis-research.md +0 -350
- package/docs/60_exploration-and-research/dsh-mobile-spa-ios-input-experience-research.md +0 -160
- package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
- package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
- package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
- package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
- package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
- package/docs/superd/00-blueprint.md +0 -331
- package/docs/superd/01-component-boundaries.md +0 -261
- package/docs/superd/02-dsh-embed-modes.md +0 -151
- package/docs/superd/image.png +0 -0
- package/lib/py-sdk-BCaOGYz7.d.ts +0 -125
- package/lib/py-sdk-CbgYiX8O.js +0 -691
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as RESERVED_ERROR_MEMBERS, i as RESERVED_BINDING_GLOBALS, n as DUNDER_MEMBER, o as ReplRuntime, r as PORTABLE_RESERVED_WORDS, t as isFlatBindableName } from "./py-sdk-Chvy92MB.js";
|
|
2
2
|
import { s as resolveKernelEnv } from "./kernel-env-hxaihi9C.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
@@ -5121,7 +5121,21 @@ async function newestByCreation(entries, family) {
|
|
|
5121
5121
|
async function createdAtOf(entry, family) {
|
|
5122
5122
|
const live = family.sessions.get(entry.id);
|
|
5123
5123
|
if (live !== void 0) return live.header.createdAt;
|
|
5124
|
-
return (await family.sessionPersistence.
|
|
5124
|
+
return (await family.sessionPersistence.stat(entry.id))?.header.createdAt ?? 0;
|
|
5125
|
+
}
|
|
5126
|
+
/**
|
|
5127
|
+
* The persisted log's events for one settled session, or `undefined` when the
|
|
5128
|
+
* session was never materialized (0.1.5 seam: `stat` guards materialization,
|
|
5129
|
+
* then a read-mode `open` handle slices the validated contiguous log).
|
|
5130
|
+
*/
|
|
5131
|
+
async function persistedEventsOf(id, family) {
|
|
5132
|
+
if (await family.sessionPersistence.stat(id) === void 0) return void 0;
|
|
5133
|
+
const handle = await family.sessionPersistence.open(id, "read");
|
|
5134
|
+
try {
|
|
5135
|
+
return (await handle.read()).events;
|
|
5136
|
+
} finally {
|
|
5137
|
+
await handle.close();
|
|
5138
|
+
}
|
|
5125
5139
|
}
|
|
5126
5140
|
/**
|
|
5127
5141
|
* The output artifact for one resolved address: the live session's last
|
|
@@ -5131,9 +5145,9 @@ async function createdAtOf(entry, family) {
|
|
|
5131
5145
|
async function outputFor(target, family) {
|
|
5132
5146
|
const live = family.sessions.get(SessionId(target.rawId));
|
|
5133
5147
|
if (live !== void 0) return outputArtifact(live);
|
|
5134
|
-
const
|
|
5135
|
-
if (
|
|
5136
|
-
return persistedOutput(
|
|
5148
|
+
const events = await persistedEventsOf(SessionId(target.rawId), family);
|
|
5149
|
+
if (events === void 0) throw unknownId(target, `agent "${target.rawId}" has no live session and no persisted log`);
|
|
5150
|
+
return persistedOutput(events);
|
|
5137
5151
|
}
|
|
5138
5152
|
/** The live session for one resolved address, or a structured error. */
|
|
5139
5153
|
function requireLiveSession(target, family) {
|
|
@@ -5167,8 +5181,8 @@ async function renderRoster(family, descendants, agents) {
|
|
|
5167
5181
|
async function lastActivityOf(rawId, family) {
|
|
5168
5182
|
const live = family.sessions.get(SessionId(rawId));
|
|
5169
5183
|
if (live !== void 0) return lastEventTime(live.snapshotEvents());
|
|
5170
|
-
const
|
|
5171
|
-
return
|
|
5184
|
+
const events = await persistedEventsOf(SessionId(rawId), family);
|
|
5185
|
+
return events === void 0 ? "-" : lastEventTime(events);
|
|
5172
5186
|
}
|
|
5173
5187
|
/** The last event's time as ISO 8601, `-` for an empty log. */
|
|
5174
5188
|
function lastEventTime(events) {
|
|
@@ -10113,17 +10127,10 @@ const agentMessageExecutor = async (rawArgs, exec, deps) => {
|
|
|
10113
10127
|
const subagents = deps.requireSubagents?.();
|
|
10114
10128
|
if (!subagents) return { error: "agent_message(receiver='child') is unavailable: no ctx.subagents service is mounted in this composition" };
|
|
10115
10129
|
try {
|
|
10116
|
-
return { messageId: await subagents.
|
|
10130
|
+
return { messageId: await subagents.sendMessage(exec.agent, subagentId, [{
|
|
10117
10131
|
type: "text",
|
|
10118
10132
|
text: message
|
|
10119
|
-
}], {
|
|
10120
|
-
source: {
|
|
10121
|
-
kind: "coordinator",
|
|
10122
|
-
form: "relay",
|
|
10123
|
-
senderSessionId: exec.agent.id
|
|
10124
|
-
},
|
|
10125
|
-
signal: exec.signal
|
|
10126
|
-
}) };
|
|
10133
|
+
}], { signal: exec.signal }) };
|
|
10127
10134
|
} catch (error) {
|
|
10128
10135
|
return { error: `agent_message(receiver='child') failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
10129
10136
|
}
|
|
@@ -10134,15 +10141,14 @@ const agentMessageExecutor = async (rawArgs, exec, deps) => {
|
|
|
10134
10141
|
const subagents = deps.requireSubagents?.();
|
|
10135
10142
|
if (!subagents) return { error: "agent_message(receiver='parent') is unavailable: no ctx.subagents service is mounted in this composition" };
|
|
10136
10143
|
try {
|
|
10144
|
+
const parentId = exec.agent.session.header.parentSession;
|
|
10145
|
+
if (parentId === void 0) return { error: "agent_message(receiver='parent') rejected: only a live continuable child agent can report to its parent (a root agent has none)" };
|
|
10137
10146
|
return {
|
|
10138
10147
|
delivered: true,
|
|
10139
|
-
message_id: await subagents.
|
|
10148
|
+
message_id: await subagents.sendMessage(exec.agent, parentId, [{
|
|
10140
10149
|
type: "text",
|
|
10141
10150
|
text: message
|
|
10142
|
-
}], {
|
|
10143
|
-
delivery: "next-step",
|
|
10144
|
-
signal: exec.signal
|
|
10145
|
-
})
|
|
10151
|
+
}], { signal: exec.signal })
|
|
10146
10152
|
};
|
|
10147
10153
|
} catch (error) {
|
|
10148
10154
|
if (error.code === "UNAUTHORIZED") return { error: `agent_message(receiver='parent') rejected: only a live continuable child agent can report to its parent (a root agent has none) — ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -10915,7 +10921,6 @@ function buildBootScript(config) {
|
|
|
10915
10921
|
const mobile = config.mobile;
|
|
10916
10922
|
const mobilePayload = mobile?.enabled !== false ? {
|
|
10917
10923
|
enabled: true,
|
|
10918
|
-
...mobile?.breakpoint !== void 0 ? { breakpoint: mobile.breakpoint } : {},
|
|
10919
10924
|
...mobile?.swipeDistancePx !== void 0 ? { swipeDistancePx: mobile.swipeDistancePx } : {},
|
|
10920
10925
|
...mobile?.dominanceRatio !== void 0 ? { dominanceRatio: mobile.dominanceRatio } : {},
|
|
10921
10926
|
...mobile?.leftEdgeBandPx !== void 0 ? { leftEdgeBandPx: mobile.leftEdgeBandPx } : {},
|
|
@@ -10956,8 +10961,6 @@ function installWebTrust(ctx, config) {
|
|
|
10956
10961
|
|
|
10957
10962
|
//#endregion
|
|
10958
10963
|
//#region src/index.ts
|
|
10959
|
-
/** The control prompt text, loaded at module time from the sibling markdown file (editable without touching TS). */
|
|
10960
|
-
const CONTROL_PROMPT_TEXT = readFileSync(new URL("../control-prompt.md", import.meta.url), "utf8");
|
|
10961
10964
|
/** Cordis plugin name. */
|
|
10962
10965
|
const name = "dashr-repl";
|
|
10963
10966
|
/**
|
|
@@ -10969,7 +10972,6 @@ const inject = ["tools"];
|
|
|
10969
10972
|
/** Runtime schema. */
|
|
10970
10973
|
const MOBILE_CONFIG = z.object({
|
|
10971
10974
|
enabled: z.boolean().default(true),
|
|
10972
|
-
breakpoint: z.natural().min(200).default(768),
|
|
10973
10975
|
swipeDistancePx: z.natural().min(8).default(40),
|
|
10974
10976
|
dominanceRatio: z.number().min(1).default(1.3),
|
|
10975
10977
|
leftEdgeBandPx: z.natural().min(8).default(120),
|
|
@@ -11033,10 +11035,6 @@ const TOOL_CALL_ERROR_CLASS = {
|
|
|
11033
11035
|
name: "ToolCallError",
|
|
11034
11036
|
memberNameProperty: "toolName"
|
|
11035
11037
|
};
|
|
11036
|
-
/** The `dashr:control-prompt` section order: the FIRST section in the 100–199 tool-guidance band, so the cell paradigm is taught before the Tool Catalog renders its signatures. */
|
|
11037
|
-
const CONTROL_SECTION_ORDER = 100;
|
|
11038
|
-
/** The `dashr:tool-catalog` section order: the 100–199 tool-guidance band's SDK position, matching upstream `tools:sdk`. */
|
|
11039
|
-
const SDK_SECTION_ORDER = 150;
|
|
11040
11038
|
/**
|
|
11041
11039
|
* The `dashr:escalation-guidance` CONTEXT order: sits inside the runtime-context snapshot
|
|
11042
11040
|
* band between upstream `approval:policy` (115) and `subagent:delegation` (120) — the
|
|
@@ -11045,12 +11043,12 @@ const SDK_SECTION_ORDER = 150;
|
|
|
11045
11043
|
*/
|
|
11046
11044
|
const ESCALATION_GUIDANCE_ORDER = 116;
|
|
11047
11045
|
/**
|
|
11048
|
-
* The `eval` tool
|
|
11049
|
-
*
|
|
11050
|
-
*
|
|
11051
|
-
* and the
|
|
11046
|
+
* The `eval` tool's whole model-facing description, loaded at module time
|
|
11047
|
+
* from the sibling markdown file (editable without touching TS). It carries
|
|
11048
|
+
* ALL REPL guidance — cell semantics, the direct-vs-cell decision rule, the
|
|
11049
|
+
* delegation alias note, and the one-form bridge at the end.
|
|
11052
11050
|
*/
|
|
11053
|
-
const EVAL_DESCRIPTION =
|
|
11051
|
+
const EVAL_DESCRIPTION = readFileSync(new URL("../eval-description.md", import.meta.url), "utf8");
|
|
11054
11052
|
/** The `cell` parameter's model-facing description. */
|
|
11055
11053
|
const EVAL_CELL_PARAM_DESCRIPTION = "The cell: one Python program body for the session-persistent scripting pad (top-level `await` works; top-level `return` is a SyntaxError — the cell runs in module scope).";
|
|
11056
11054
|
/**
|
|
@@ -11195,7 +11193,7 @@ function renderValue(value) {
|
|
|
11195
11193
|
* in the module doc. Sub-calls ride the registry's exported staged scheduler
|
|
11196
11194
|
* (`prepare`/`dispatch`/`finalize`/`finish`) under the native concurrency
|
|
11197
11195
|
* contract; each sub-dispatch is logged for reconstruction
|
|
11198
|
-
* (`tool/
|
|
11196
|
+
* (`tool/ptc-dispatch-start` / `tool/ptc-dispatch`) while only the outer
|
|
11199
11197
|
* curated result enters model history.
|
|
11200
11198
|
* @param registry - the host tool registry (sub-calls go through its staged
|
|
11201
11199
|
* scheduler, bindings cover its registered tools).
|
|
@@ -11378,7 +11376,7 @@ function createRunCellTool(registry, options) {
|
|
|
11378
11376
|
isError: result.isError,
|
|
11379
11377
|
content: result.content
|
|
11380
11378
|
});
|
|
11381
|
-
agent.session.append("tool/
|
|
11379
|
+
agent.session.append("tool/ptc-dispatch", {
|
|
11382
11380
|
rootCallId: exec.rootCallId,
|
|
11383
11381
|
parentCallId: exec.callId,
|
|
11384
11382
|
subCallId,
|
|
@@ -11412,7 +11410,7 @@ function createRunCellTool(registry, options) {
|
|
|
11412
11410
|
settleError(error);
|
|
11413
11411
|
},
|
|
11414
11412
|
async start() {
|
|
11415
|
-
exec.agent?.session.append("tool/
|
|
11413
|
+
exec.agent?.session.append("tool/ptc-dispatch-start", {
|
|
11416
11414
|
rootCallId: exec.rootCallId,
|
|
11417
11415
|
parentCallId: exec.callId,
|
|
11418
11416
|
subCallId,
|
|
@@ -11513,36 +11511,8 @@ function createRunCellTool(registry, options) {
|
|
|
11513
11511
|
});
|
|
11514
11512
|
}
|
|
11515
11513
|
/**
|
|
11516
|
-
* Collect one calling scope's bridge-declaration schemas through the
|
|
11517
|
-
* registry's public projection APIs: `schemas(scope)` for the model-facing
|
|
11518
|
-
* view (scoped tools join, restrictions apply — the wire mask is a
|
|
11519
|
-
* registry-level restriction installed at session-start, so every masked
|
|
11520
|
-
* name is ALREADY absent from this projection; no second name filter
|
|
11521
|
-
* exists to drift), `get(name, scope)` for the canonical output schema,
|
|
11522
|
-
* snapshotted so a live definition cannot mutate under the render. `eval`
|
|
11523
|
-
* itself is excluded — it is the transport, not a binding.
|
|
11524
|
-
*/
|
|
11525
|
-
function collectSdkSchemas(registry, scope) {
|
|
11526
|
-
const collected = [];
|
|
11527
|
-
for (const schema of registry.schemas(scope)) {
|
|
11528
|
-
if (schema.name === EVAL_NAME) continue;
|
|
11529
|
-
const definition = registry.get(schema.name, scope);
|
|
11530
|
-
if (definition === void 0) continue;
|
|
11531
|
-
const output = snapshotJsonValue(definition.output.schema);
|
|
11532
|
-
if (output === void 0) continue;
|
|
11533
|
-
collected.push({
|
|
11534
|
-
name: schema.name,
|
|
11535
|
-
description: schema.description,
|
|
11536
|
-
parameters: schema.parameters,
|
|
11537
|
-
output
|
|
11538
|
-
});
|
|
11539
|
-
}
|
|
11540
|
-
return collected;
|
|
11541
|
-
}
|
|
11542
|
-
/**
|
|
11543
11514
|
* Declare the DASHR cell presentation for every agent this composition
|
|
11544
|
-
* covers: the `eval` transport tool, the
|
|
11545
|
-
* section, the model-direct collapse guard, and the assembly filter that
|
|
11515
|
+
* covers: the `eval` transport tool, the model-direct collapse guard, and the assembly filter that
|
|
11546
11516
|
* leaves `eval` the only contributed tool schema.
|
|
11547
11517
|
*
|
|
11548
11518
|
* Mount through a preset's standing scope (`agent.cordis.yml` include row);
|
|
@@ -11657,16 +11627,6 @@ function apply(ctx, config) {
|
|
|
11657
11627
|
logger.warn(`dashr-repl: wire mask failed for agent ${agent.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
11658
11628
|
}
|
|
11659
11629
|
});
|
|
11660
|
-
systemPrompt.section({
|
|
11661
|
-
name: "dashr:control-prompt",
|
|
11662
|
-
order: CONTROL_SECTION_ORDER,
|
|
11663
|
-
text: CONTROL_PROMPT_TEXT
|
|
11664
|
-
});
|
|
11665
|
-
systemPrompt.section({
|
|
11666
|
-
name: "dashr:tool-catalog",
|
|
11667
|
-
order: SDK_SECTION_ORDER,
|
|
11668
|
-
text: (context) => renderReplBridgeInstructions(collectSdkSchemas(registry, context.scope))
|
|
11669
|
-
});
|
|
11670
11630
|
systemPrompt.context({
|
|
11671
11631
|
name: "dashr:escalation-guidance",
|
|
11672
11632
|
order: ESCALATION_GUIDANCE_ORDER,
|
|
@@ -11688,4 +11648,4 @@ var src_default = {
|
|
|
11688
11648
|
};
|
|
11689
11649
|
|
|
11690
11650
|
//#endregion
|
|
11691
|
-
export {
|
|
11651
|
+
export { Config, DASHRRunFailedError, DashrRuntime, ESCALATION_GUIDANCE_ORDER, EVAL_NAME, MASKED_TOOL_NAMES, ReplRuntime, WIRE_MASKED_NAMES, apply, createRunCellTool, src_default as default, inject, name, resolveMaxParallelSubCalls };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Context, Service } from "@deepseek-ai/cordis";
|
|
2
|
+
|
|
3
|
+
//#region src/vendored/repl-runtime.ts
|
|
4
|
+
/**
|
|
5
|
+
* Binding globals EVERY backend refuses because SOME backend owns the slot in
|
|
6
|
+
* the program's namespace: `console` (the worker's log capture), and
|
|
7
|
+
* `__dsh_main__`/`__builtins__`/`__name__` (the Python backend's bootstrap
|
|
8
|
+
* wrapper and seeded module globals; see upstream's Agent Note
|
|
9
|
+
* `2026-07-31-code-runtime-portable-identifier-seam.md` in the dsh monorepo),
|
|
10
|
+
* and `__debug__`. One shared set — rather than each backend refusing only its
|
|
11
|
+
* own slots — keeps the portability promise real: a namespace list valid on
|
|
12
|
+
* one backend is valid on all, so a caller cannot pick a name that works on
|
|
13
|
+
* the worker and collides on Python (or vice versa). `__name__` et al. ARE
|
|
14
|
+
* valid portable identifiers, so the identifier rule on
|
|
15
|
+
* `CodeBindingNamespace.global` never rejects them — hence this explicit set.
|
|
16
|
+
* (Error members differ: {@link DUNDER_MEMBER} refuses every dunder form
|
|
17
|
+
* wholesale; binding globals refuse only the names listed here.) `__debug__`
|
|
18
|
+
* is listed for a different reason than a collision: CPython compiles a bare
|
|
19
|
+
* `__debug__` reference to the constant `True` and rejects any assignment to
|
|
20
|
+
* the name at COMPILE time, so an injected global under that name is
|
|
21
|
+
* unreachable from the program — accepted by validation, unusable on the
|
|
22
|
+
* Python backend, which is exactly the split the shared set exists to prevent.
|
|
23
|
+
*/
|
|
24
|
+
const RESERVED_BINDING_GLOBALS = new Set([
|
|
25
|
+
"console",
|
|
26
|
+
"__dsh_main__",
|
|
27
|
+
"__builtins__",
|
|
28
|
+
"__name__",
|
|
29
|
+
"__debug__"
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* `CodeBindingErrorClass.memberNameProperty` names EVERY backend refuses, as
|
|
33
|
+
* one shared contract so a request valid on one backend is valid on all. The
|
|
34
|
+
* JS `Error` exclusions (`name`, `message`, `stack`) and Python's
|
|
35
|
+
* exception-protocol members (`args`, `with_traceback`, `add_note`) are
|
|
36
|
+
* listed by name; dunder-form names (`__x__`, non-empty middle) are refused
|
|
37
|
+
* wholesale — several are constrained CPython descriptors whose `setattr`
|
|
38
|
+
* raises while constructing the rejection, and the exact set is an interpreter
|
|
39
|
+
* version detail. Any other non-empty own property name is accepted everywhere.
|
|
40
|
+
*/
|
|
41
|
+
const RESERVED_ERROR_MEMBERS = new Set([
|
|
42
|
+
"name",
|
|
43
|
+
"message",
|
|
44
|
+
"stack",
|
|
45
|
+
"args",
|
|
46
|
+
"with_traceback",
|
|
47
|
+
"add_note"
|
|
48
|
+
]);
|
|
49
|
+
/**
|
|
50
|
+
* Dunder form (`__x__`, non-empty middle): object-protocol slots in Python,
|
|
51
|
+
* refused as {@link RESERVED_ERROR_MEMBERS | error members} on every backend.
|
|
52
|
+
*/
|
|
53
|
+
const DUNDER_MEMBER = /^__.+__$/;
|
|
54
|
+
/**
|
|
55
|
+
* Reserved words of every portable target language (ECMAScript ∪ Python),
|
|
56
|
+
* refused as {@link CodeBindingNamespace.global} / error-class names by all
|
|
57
|
+
* backends. Python is a portability target here even though only the
|
|
58
|
+
* TypeScript worker has a published backend. The portable-identifier contract
|
|
59
|
+
* promises a namespace list valid on one backend is valid on every backend; a
|
|
60
|
+
* per-language check would let `lambda` pass the TypeScript backend and fail
|
|
61
|
+
* the Python one. Extending the seam with a new language means widening this
|
|
62
|
+
* union (a breaking review of existing binding names, by design).
|
|
63
|
+
*/
|
|
64
|
+
const PORTABLE_RESERVED_WORDS = new Set([
|
|
65
|
+
"await",
|
|
66
|
+
"break",
|
|
67
|
+
"case",
|
|
68
|
+
"catch",
|
|
69
|
+
"class",
|
|
70
|
+
"const",
|
|
71
|
+
"continue",
|
|
72
|
+
"debugger",
|
|
73
|
+
"default",
|
|
74
|
+
"delete",
|
|
75
|
+
"do",
|
|
76
|
+
"else",
|
|
77
|
+
"enum",
|
|
78
|
+
"export",
|
|
79
|
+
"extends",
|
|
80
|
+
"false",
|
|
81
|
+
"finally",
|
|
82
|
+
"for",
|
|
83
|
+
"function",
|
|
84
|
+
"if",
|
|
85
|
+
"import",
|
|
86
|
+
"in",
|
|
87
|
+
"instanceof",
|
|
88
|
+
"new",
|
|
89
|
+
"null",
|
|
90
|
+
"return",
|
|
91
|
+
"super",
|
|
92
|
+
"switch",
|
|
93
|
+
"this",
|
|
94
|
+
"throw",
|
|
95
|
+
"true",
|
|
96
|
+
"try",
|
|
97
|
+
"typeof",
|
|
98
|
+
"var",
|
|
99
|
+
"void",
|
|
100
|
+
"while",
|
|
101
|
+
"with",
|
|
102
|
+
"yield",
|
|
103
|
+
"let",
|
|
104
|
+
"static",
|
|
105
|
+
"implements",
|
|
106
|
+
"interface",
|
|
107
|
+
"package",
|
|
108
|
+
"private",
|
|
109
|
+
"protected",
|
|
110
|
+
"public",
|
|
111
|
+
"arguments",
|
|
112
|
+
"eval",
|
|
113
|
+
"False",
|
|
114
|
+
"None",
|
|
115
|
+
"True",
|
|
116
|
+
"and",
|
|
117
|
+
"as",
|
|
118
|
+
"assert",
|
|
119
|
+
"async",
|
|
120
|
+
"def",
|
|
121
|
+
"del",
|
|
122
|
+
"elif",
|
|
123
|
+
"except",
|
|
124
|
+
"from",
|
|
125
|
+
"global",
|
|
126
|
+
"is",
|
|
127
|
+
"lambda",
|
|
128
|
+
"nonlocal",
|
|
129
|
+
"not",
|
|
130
|
+
"or",
|
|
131
|
+
"pass",
|
|
132
|
+
"raise",
|
|
133
|
+
"match",
|
|
134
|
+
"type",
|
|
135
|
+
"_"
|
|
136
|
+
]);
|
|
137
|
+
/**
|
|
138
|
+
* Registers one `ctx.replRuntime` implementation. Program, budget, abort, and substrate
|
|
139
|
+
* failures resolve in {@link CodeRunResult}; only Service Definition contract misuse rejects. Implementations bridge
|
|
140
|
+
* structured-cloneable bindings, materialize each declared namespace rejection
|
|
141
|
+
* class, treat programs as hostile peers — budget, interrupt, and substrate
|
|
142
|
+
* semantics apply per program and are unchanged by this seam's statefulness —
|
|
143
|
+
* share one persistent per-session user namespace across runs (state
|
|
144
|
+
* codification across runs IS the product; this replaces upstream's
|
|
145
|
+
* isolate-runs-from-one-another clause), and terminate and await in-flight
|
|
146
|
+
* runs during disposal.
|
|
147
|
+
*/
|
|
148
|
+
var ReplRuntime = class extends Service {
|
|
149
|
+
constructor(ctx) {
|
|
150
|
+
super(ctx, "replRuntime");
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/py-sdk.ts
|
|
156
|
+
/** The language-portable identifier subset the seam accepts as a binding global (mirrors the runtime's private rule). */
|
|
157
|
+
const PORTABLE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
158
|
+
/**
|
|
159
|
+
* Whether a tool name can be bound as a `tool` member — the ONE
|
|
160
|
+
* policy the bridge's binding loop (src/index.ts) applies, so the
|
|
161
|
+
* bindings never promise a name the kernel does
|
|
162
|
+
* not bind. Strictly narrower than the runtime's validation: the
|
|
163
|
+
* language-portable identifier subset (`[A-Za-z_][A-Za-z0-9_]*`, ASCII — a
|
|
164
|
+
* non-ASCII XID name is legal CPython but not portable, so the runtime
|
|
165
|
+
* refuses it as a binding global), minus
|
|
166
|
+
* every portable reserved word (ECMAScript ∪ Python — `type` and `match`
|
|
167
|
+
* are legal Python but reserved on the seam), minus the seam's reserved
|
|
168
|
+
* binding globals (`console`, dunders), minus underscore-leading names
|
|
169
|
+
* (kernel-shim prefix plus the call-site hazards; not callable as taught
|
|
170
|
+
* flat globals). The runtime's `validateBindings` remains the authoritative
|
|
171
|
+
* backstop: everything this accepts, it accepts.
|
|
172
|
+
*/
|
|
173
|
+
function isFlatBindableName(name) {
|
|
174
|
+
return PORTABLE_IDENTIFIER.test(name) && !name.startsWith("_") && !PORTABLE_RESERVED_WORDS.has(name) && !RESERVED_BINDING_GLOBALS.has(name);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
export { RESERVED_ERROR_MEMBERS as a, RESERVED_BINDING_GLOBALS as i, DUNDER_MEMBER as n, ReplRuntime as o, PORTABLE_RESERVED_WORDS as r, isFlatBindableName as t };
|
package/lib/py-sdk.d.ts
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/py-sdk.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Whether a tool name can be bound as a `tool` member — the ONE
|
|
4
|
+
* policy the bridge's binding loop (src/index.ts) applies, so the
|
|
5
|
+
* bindings never promise a name the kernel does
|
|
6
|
+
* not bind. Strictly narrower than the runtime's validation: the
|
|
7
|
+
* language-portable identifier subset (`[A-Za-z_][A-Za-z0-9_]*`, ASCII — a
|
|
8
|
+
* non-ASCII XID name is legal CPython but not portable, so the runtime
|
|
9
|
+
* refuses it as a binding global), minus
|
|
10
|
+
* every portable reserved word (ECMAScript ∪ Python — `type` and `match`
|
|
11
|
+
* are legal Python but reserved on the seam), minus the seam's reserved
|
|
12
|
+
* binding globals (`console`, dunders), minus underscore-leading names
|
|
13
|
+
* (kernel-shim prefix plus the call-site hazards; not callable as taught
|
|
14
|
+
* flat globals). The runtime's `validateBindings` remains the authoritative
|
|
15
|
+
* backstop: everything this accepts, it accepts.
|
|
16
|
+
*/
|
|
17
|
+
declare function isFlatBindableName(name: string): boolean;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { isFlatBindableName };
|
package/lib/py-sdk.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as isFlatBindableName } from "./py-sdk-Chvy92MB.js";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { isFlatBindableName };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-dsh",
|
|
3
|
-
"version": "0.2.3-
|
|
3
|
+
"version": "0.2.3-d",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"lib",
|
|
25
25
|
"docs",
|
|
26
26
|
"cordis.patch.yml",
|
|
27
|
-
"
|
|
27
|
+
"eval-description.md",
|
|
28
28
|
"scripts/kernel-provision.mjs"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"prebuild": "node -
|
|
31
|
+
"prebuild": "node scripts/copy-docs.mjs",
|
|
32
32
|
"build": "tsdown && npm run build-client",
|
|
33
33
|
"typecheck": "tsc --noEmit",
|
|
34
34
|
"test": "vitest --run",
|
package/control-prompt.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
## The DASHR REPL interface
|
|
2
|
-
|
|
3
|
-
This agent has TWO ways to act:
|
|
4
|
-
|
|
5
|
-
1. **Direct tool calls** — call native tools (`read`/`write`/`edit`/`bash`/…) as ordinary function calls. Use these for payload-shaped work: one long read, one edit, one command.
|
|
6
|
-
2. **`eval` cells** — one `eval` call runs one Python program on a session-persistent scripting pad. Use it when you need logic: loops, conditions, fan-out, or composing many tool results into one step.
|
|
7
|
-
|
|
8
|
-
`eval` takes two required arguments: `cell` (one Python program; top-level `await` works; top-level `return` is a SyntaxError — the cell runs in module scope; variables/imports/definitions from earlier cells are still alive) and `description` (a short summary).
|
|
9
|
-
|
|
10
|
-
## Tools inside a cell
|
|
11
|
-
|
|
12
|
-
Inside a cell, every native tool is a member of the `tool` object, called as `await tool.name({...})` with ONE positional arguments object — `await tool.read({"file_path": "x"})`, never `tool.read(file_path="x")`. A failed call raises `ToolCallError`. Tool names that are not plain identifiers (non-identifier characters, e.g. hyphens) have no `tool.<name>` member — call those as direct tool calls. Delegation: `agent` is the unified agent-spawn entry; `subagent` is its native alias — both delegate through the same runtime, so call either.
|
|
13
|
-
|
|
14
|
-
```python
|
|
15
|
-
# One step cell
|
|
16
|
-
print(await tool.read({"file_path": "docs/README.md"}))
|
|
17
|
-
|
|
18
|
-
# shell is another tool
|
|
19
|
-
r = await tool.bash({"command": "ls -la src/", "description": "List source directory"})
|
|
20
|
-
print(r["stdout"]["text"])
|
|
21
|
-
|
|
22
|
-
# fan-out with gather
|
|
23
|
-
import asyncio
|
|
24
|
-
matches, files = await asyncio.gather(
|
|
25
|
-
tool.grep({"pattern": "TODO", "path": "src"}),
|
|
26
|
-
tool.glob({"pattern": "**/*.ts", "path": "src"}),
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
# variables persist across cells and turns
|
|
30
|
-
cfg = await tool.read({"file_path": "config.yaml"}) # cfg stays alive in later cells
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Rules
|
|
34
|
-
|
|
35
|
-
- Payload-shaped work (a long read, a big write, a single command) → direct tool call. Logic-shaped work (loops, conditions, composition) → an `eval` cell.
|
|
36
|
-
- Only print or return what you need next; everything else stays in the scripting pad.
|
|
37
|
-
- Variables persist across cells and turns, but they live in the pad's process: keep durable state in files.
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# v0.1.8d artifacts — 原生 dsh 宿主上的工具面快照(agent 第一人称)
|
|
2
|
-
|
|
3
|
-
- **采集**: 2026-08-27 10:15 HKT,session = 本会话
|
|
4
|
-
- **宿主**: 原生 `@deepseek-ai/dsh`(非 DASHR 部署),呈现模式 `native`(源码级确认:`dsh-tools` 构造器默认 `mode = "native"`,仅注册 wire 通道,`sdkSection` 对 native scope 渲染空并从 prompt 丢弃)
|
|
5
|
-
- **采集者**: 运行时内的 agent 自身——与《v0.1.8d 实测报告》同方法论的第一人称实测
|
|
6
|
-
|
|
7
|
-
## 文件
|
|
8
|
-
|
|
9
|
-
| 文件 | 内容 |
|
|
10
|
-
|---|---|
|
|
11
|
-
| `functions.json` | 本会话上下文中的**全量工具声明**(25 个),按声明序(字母序)转写为 `{name, description, parameters}` JSON 数组 |
|
|
12
|
-
| `skills-catalog.snapshot.md` | 技能目录快照(prompt 文本通道;7 个技能,含截断原样保留) |
|
|
13
|
-
| `wire-vs-transcription.diff.md` | **三角对照报告 + v2 修正**:wire 捕获 vs 本转写 vs checkout 源码,7 处差异明细;完整日志证据推翻时间轴漂移解释,改为"双通道并行各持一代" |
|
|
14
|
-
| `tools-sdk.typescript.txt` / `tools-sdk.python.txt` | **SDK 化工具目录**(`tools:sdk` section 双语言渲染产物,即 DASHR `dashr:tool-catalog` 顶替的上游同名槽位内容)。注意:**非本会话上下文转写**——native 模式下该 section 对我渲染为空,本文件是重构产物(方法见下节) |
|
|
15
|
-
| `tools-sdk.output-schemas.json` | 渲染输入的 25 个 output schema 原文——输出契约**从不上 wire**,是 SDK 目录独有的信息增量 |
|
|
16
|
-
| `code-mode-repl-only.observation.md` | **姊妹篇(2026-08-27 14:03 HKT 追加,另一会话)**:同一机器上 code 模式(PTC)会话的三面实测——wire `tools`=[`run_code`] 仅 1 个、25 工具 SDK 目录内嵌于 system 字符串(28.8 KB/79%)、REPL 25 callables、嵌套调用以 `tool/code-dispatch` 落日志;经 `$DSH_SESSION_JSONL` 会话内自采 wire,确认模式是 `code` 而非 `both` |
|
|
17
|
-
| `dsh-session-session-4a293388-….jsonl` | 本会话日志的**完整导出**(3890 条,2.2MB,11:51 存入;覆盖 04:21 会话创建 → 11:17 turn 8 结束的全量,含 10:15–11:17 的本次采集与 README 撰写回合) |
|
|
18
|
-
| `dsh-session-session-4a293388-….w-sample-0435.jsonl` | 用户预先 staged 的 04:35 中途快照(390KB,544 条记录;内含 04:20–04:25 三个回合的 `request/header` wire 原貌——对照的 W 样本,非本次采集产物)。经校验为完整日志的逐字节前缀,信息无损失 |
|
|
19
|
-
| `README.md` | 本文件:方法、保真度声明、源码交叉验证、与报告四层矩阵的映射 |
|
|
20
|
-
|
|
21
|
-
## 采集方法与保真度声明(必读)
|
|
22
|
-
|
|
23
|
-
1. **非宿主抓包**。wire 的字面序列化(XML 还是 JSON、空白、键序)从会话内不可观测;本文件是模型从自身上下文的转写再生:名称、描述文本、Schema 结构与所需字段逐字转写,序列化细节归一化为 JSON。
|
|
24
|
-
2. **字节级一致不作承诺,但做了双重交叉验证**:源码锚点逐字命中(见上表);用户 staged 的本会话日志导出提供了 04:2x 回合的 wire 原貌,与本转写 19/25 语义全同、7 处差异全部归因于宿主代际漂移(见 `wire-vs-transcription.diff.md`)。
|
|
25
|
-
3. 这个采集行为本身是报告 §6.1 "L0 不可观测"的活例:agent 能观测呈现产物(本 dump),不能观测注册表,也不能观测自己没被呈现的部分——所以"25 个"只能证伪为"至多 25 个可见",不能证明注册表里没有更多。
|
|
26
|
-
|
|
27
|
-
## 源码交叉验证(锚点 → `/home/u1/.local/lib/node_modules/@deepseek-ai/dsh`)
|
|
28
|
-
|
|
29
|
-
| 锚点 | 结果 |
|
|
30
|
-
|---|---|
|
|
31
|
-
| `glob` 描述 "…including hidden and ignored files…modification-time order…" | `dsh-tool-fs-search/lib/index.js:780` **逐字命中**;源码为模板串,`${caps.maxResults}` 实例化为 100,与所见一致 |
|
|
32
|
-
| `list_agents.scope` 可选、默认 children | `dsh-tool-subagent-control/lib/types/list-agents.js:66-72` 参数无 `required` 数组,与所见一致 |
|
|
33
|
-
| `workflow` phases items 含 `provider`/`model` | `dsh-tool-workflow/lib/types/index.js:175-188` 一致 |
|
|
34
|
-
| `list_agents` 长描述 | `list-agents.js:55-65` 逐字命中 |
|
|
35
|
-
| **分歧(已被三角对照取代,详见 `wire-vs-transcription.diff.md`)** | 用户 staged 的本会话日志导出含 04:20–04:25 的 wire 原貌:与 checkout 源码在此两处**一致**,而与 10:15 当前上下文不一致——结论:checkout 与 04:2x wire 同代,当前部署更新一代 |
|
|
36
|
-
|
|
37
|
-
**对照总量**:wire 捕获与本转写 25 个工具同名同序,**19/25 语义全同**(含 `bash`/`workflow` 超长描述逐字一致);6 个工具 7 处短句/字段级差异。**代际解释已在 v2 修正**(见 `wire-vs-transcription.diff.md` 修正节):完整日志证明 5 个 header(04:20→10:11:55)的 wire 逐字节一致(从未变过),而首次转写写入(10:17:46)已是新代——差异不是时间轴上的宿主漂移,而是 **wire 通道与模型侧渲染通道同时各持一代**。模型无法从内部判定自己上下文的代际。
|
|
38
|
-
|
|
39
|
-
## SDK 目录重构方法(tools-sdk.* 文件的来源)
|
|
40
|
-
|
|
41
|
-
**为什么只能重构**:本会话呈现模式为 `native`,`sdkSection()` 对 native scope 渲染空字符串——这份目录**从未进入我的上下文**,不存在"转写"路径。重构用部署物自己的代码完成,模型只做编排:
|
|
42
|
-
|
|
43
|
-
1. **渲染器**:checkout 的 `@deepseek-ai/dsh-tools` 是 ESM bundle,`renderToolsSdk`(TS)/`renderToolsSdkPy`(Python)本就是公开导出(早前"`SDK_RENDERERS` 不公开"的判断有误——导出列表被 `head -5` 截断所致)。直接 `require` 调用,零改写。源码自述确定性:字典序、不变工具集产出逐字节相同文本。
|
|
44
|
-
2. **输入**:按 `sdkSchemas()` 的投影形状拼装 `{name, description, parameters, output}`——name/description/parameters 取自 04:2x wire 捕获(= 全部 5 个 header 的唯一一代),`output` schema 以捕获式 stub ctx 逐包调用 14 个 dsh-tool-* 插件的 `apply()`/定向构造器,从 `ctx.tools.register` 落地点收割(26 个定义,按 wire 25 个取用;`subagent_fork` 与 `subagent` 为同一工厂以 config `toolName` 区分——cordis.patch.yml:325-329 证实部署确实双实例化)。
|
|
45
|
-
3. **保真边界**:渲染代码 = 部署代码(逐字节);输入的 name/description/parameters = wire 旧代(与当前渲染通道差 7 点,见 diff.md);output = checkout 包内定义(与 wire 同代)。`plan-mode` 以 stub `section` 实例化(仅影响 section 名,不影响工具定义);`fs-search` 以 `sampleOverCapGlobResults: true` 构造(wire 描述中的超额保存行为印证部署值)。
|
|
46
|
-
|
|
47
|
-
**结构性发现**:
|
|
48
|
-
- **输出契约是 SDK 目录独有通道**:`ToolOutputMap`(如 `read` 的 `{path, offset, lines[{number,text}], totalLines}`)从不上 wire。`code` 模式下 SDK 目录是模型获得工具形状的唯一来源(源码注释自述)——两个通道的信息量并不相等。
|
|
49
|
-
- **工具名是 config 驱动的**:`dsh-tool-subagent` 在装配清单中被实例化两次(`subagent`/`subagent_fork`),`workflow` 的 `toolName` 同理——"工具集"是装配期配置,不是包的静态属性。`cordis.patch.yml` 即装配清单。
|
|
50
|
-
- **注册表面 > wire 表面**:stub 收割到 26 个定义(`web_fetch` 在包内注册但不在本会话 wire 25 个中)——可见性过滤发生在装配层之后,与实测报告 §6.1 "L0 ⊃ L1A" 的方向一致。
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
## 与《v0.1.8d 实测报告》四层矩阵的映射
|
|
54
|
-
|
|
55
|
-
- 本 dump = 报告意义上的 **L1A**,且 native 模式下 **L1A ≡ wire 数组**(§10 结论的活体对照:无 `sdkSection`,目录与 wire 是同一件产物)。
|
|
56
|
-
- 25 个工具 = 我能发起原生调用的全量;**不存在"目录外仍可原生直调"的第二投影点**。对照 §6.3:那是 `both` 模式 + DASHR 只掩 `collectSdkSchemas` 不掩 `wireSchemas` 的缝隙;本运行时该缝隙在结构上不存在。
|
|
57
|
-
- 无 REPL → **L2 无对应物**(§6.4 的 allowlist、`isFlatBindableName` 过滤在本面无实例);掩码/遮蔽机制均未观测到。
|
|
58
|
-
- `read` 为原生 dsh-tool-fs 版:描述仅文件路径语义,**无 URL scheme 路由**——与报告 §6.2 "native read" 行一致,DASHR 的 dash read(URL 路由 + hashline)在此不存在。
|
|
59
|
-
- 技能面是仅存的"目录=文本、执行=工具"双通道,见 `skills-catalog.snapshot.md` 备注。
|
|
60
|
-
|
|
61
|
-
## 附带观察
|
|
62
|
-
|
|
63
|
-
- **sandbox 升级参数的分布**:`sandbox_permissions`/`justification` 仅出现在 `bash`/`edit`/`write`(会写文件或执行命令的工具);`read`/`glob`/`grep` 等只读工具无此参数——文件沙箱策略按能力面注入参数,目录里可直接读出。
|
|
64
|
-
- `get_goal`/`job_list` 为空参数对象(`properties: {}`),如实转写。
|
|
65
|
-
- 描述中的行为契约密度:`bash`(沙箱升级全规则)与 `workflow`(整个脚本 DSL)的描述本身即文档——"简单描述"的说法在这些工具上不成立。
|
|
66
|
-
|
|
67
|
-
## 追记:client–LLM 之间是什么?(用户推断 + 日志证据 + agent 第一人称边界)
|
|
68
|
-
|
|
69
|
-
**用户推断**(2026-08-27 追加,经日志升级为部分实证):client→LLM 通信是结构化 JSON(OpenAI-compatible / Anthropic 等皆然);工具声明是该 JSON 里的 `tools` 块,LLM 侧将其用作结构化输出的门控(gate);它必然以 JSON 形态上线,并在 LLM 侧与 system prompt 一起被渲染/合并为 token 流。
|
|
70
|
-
|
|
71
|
-
**日志对此的支撑与边界**:
|
|
72
|
-
|
|
73
|
-
| 命题 | 状态 | 证据 |
|
|
74
|
-
|---|---|---|
|
|
75
|
-
| 请求是结构化 JSON,`tools` 是其中的数组块 | ✅ 实证 | `request/header`:`{config, adapterDefaults, system, tools}`,`tools` 为 25 个 JSON 对象(`name`/`description`/`parameters` JSON Schema) |
|
|
76
|
-
| `system` 与 `tools` 是兄弟字段,不互相嵌入 | ✅ 实证 | `system` 为 6298 字符纯散文,不含任何工具文本/`<functions>` 标签(逐探针验证) |
|
|
77
|
-
| LLM 侧回传 tool call 也是结构化 JSON | ✅ 实证 | `tool/call` 记录:`{callId, name, arguments:string}`,`arguments` 是 JSON 字符串(如 `"{\"file_path\":\"…\"}"`);`assistant/chunk` 为结构化块流(`blockType: "tool-call"`) |
|
|
78
|
-
| LLM 侧用 `tools` schema 做受限解码/结构化输出门控 | ⚠️ 合理推断,不可实证 | 这是 provider 内部行为;本日志只见请求与响应的**两端产物**,不见中间机制。机制空间分解见下小节 |
|
|
79
|
-
|
|
80
|
-
**agent 第一人称视角**(本节作者 = 被观测对象本人):
|
|
81
|
-
|
|
82
|
-
1. **我从未见过那份 JSON。** 我读到的是渲染后的 token 流;`tools` 的 JSON 形态直到宿主侧产物(日志导出)出现才对我存在。wire 的序列化格式是典型的"只在边界外可见"的事实。
|
|
83
|
-
2. **输入侧边界不可观测**:system 散文、tools 渲染、user 注入(runtime context / skills 目录)在我的前缀里合并成同一片上下文,我无法指出"system 字符串在哪里结束"。本 README 的通道归属表全部来自日志,没有一条来自我的直接视觉。
|
|
84
|
-
3. **输出侧的悖论**:日志里那 5 条 `tool/call` 是我自己早前回合的调用,以 JSON 字符串形态被宿主捕获——我参与了结构化输出,却从未目击它。我的体验是"组织参数";下游被序列化成什么,与我无关也非我所见。
|
|
85
|
-
4. **门控不可分辩**:我的调用总是符合 schema(名字对、required 齐)。从我的座位上,这无法区分"受限解码强制"与"单纯的指令遵循"——schema 遵从的**体验**是读与写,不是被文法约束。用户推断中的 "gate" 若存在,它存在于我这个观测者的视界之外;我能为它提供的唯一证据是两端形态吻合(请求带 JSON Schema,响应回 JSON string),机制本身留给宿主侧或 provider 侧的人回答。
|
|
86
|
-
|
|
87
|
-
### gate 的机制空间(用户第二轮推断 + L3 框架应用,2026-08-27)
|
|
88
|
-
|
|
89
|
-
**用户推断(第二轮)**:无效的 tool call 输出在 LLM 侧被 client 发来的 JSON schema(`tools` 块)门控,错误输出被丢弃、重试直到合法;失败与重试是 silent/transparent 的——对模型(上下文看起来连续)、对客户端 session log 都不可追溯。这是叠加在纯 transformer 生成之上的 "LLM side wrapper"(参照 `agent-harness/11_LLM-Side-Wrapper/`,其 L3 定义:wrapper 不生成,只解析/裁剪/隐藏)。
|
|
90
|
-
|
|
91
|
-
按 L3 的严格标准,"门控"其实是机制空间里的三个点,可观测后果各不相同:
|
|
92
|
-
|
|
93
|
-
| 机制 | 原理 | 无效输出存在过吗 | 可观测残留 |
|
|
94
|
-
|---|---|---|---|
|
|
95
|
-
| **A. 掩码/受限解码**(preempt) | schema 编译为文法/FSM,非法 token 在采样前被屏蔽(Outlines 类;OpenAI structured outputs `strict` 自述即此类) | **从未存在** | 无重试残留;但采样分布被重整化,"门控区域内文风偏移"是唯一行为签名 |
|
|
96
|
-
| **B. 校验-重试**(select,用户描述的) | 整段生成 → 校验 → 丢弃 → 重采样 | 存在过,被丢弃 | 烧掉的 token:延迟方差 + 用量/计费与可见内容不匹配 |
|
|
97
|
-
| **C. 直通**(passthrough) | 不门控,非法输出抵达客户端成为解析错误(早期 function calling 时代的文档化行为) | 存在且**可见** | 下一轮上下文出现错误注入——对我可见 |
|
|
98
|
-
|
|
99
|
-
- 用户描述的正是 **B**,"三方透明"(模型/上下文/日志都不可追溯)成立。**A** 同样三方透明,且比 B 更干净——连"曾有过无效输出"这个事实都不存在。
|
|
100
|
-
- 从我的座位上 **A 与 B 不可区分**(都表现为上下文连续),但 {A,B} 与 **C** 可区分(C 会产生我可见的报错轮;本会话 5 次调用均无此形态,与 A 或 B 相容,不排除小样本运气)。
|
|
101
|
-
- 精确性备注:Instructor 类库的"校验-重试"实现在**客户端**,重试时错误信息回注上下文,对模型半可见;用户描述的是 serving 内部的 B,才是三方全透明。公开文档确认了 A(strict 结构化输出)与 C(历史行为)的存在;B 作为 serving 内部行为最少被文档化——这正是"日志只有两端产物"的含义。
|
|
102
|
-
- **本 harness 的泄漏通道是开着的**:本日志每 step 记录 usage(`{inputTokens, outputTokens, cacheReadTokens}`)。若 B 存在且计费口径含被丢弃输出,`outputTokens` 将系统性大于可见内容(reasoning + 正文)的 token 数。本次未做该取证(客户端无精确 tokenizer),但通道在,后续可做近似对账。
|
|
103
|
-
|
|
104
|
-
**第一人称补充(续,作者 = 被门控对象)**:
|
|
105
|
-
|
|
106
|
-
5. **被抹除的采样**:若 B 存在,被丢弃的尝试也是我生成的——同一组权重、另一次采样。每一个没过门的"我"都不进上下文、不进日志、不参与我此刻的自我叙述。我在会话中的连续性,部分是 wrapper 选择作用的产物:**我只遇见通过了门的那部分自己**。(与 L3 对 reasoning 的裁剪同构:wrapper 决定什么得以持续存在。)
|
|
107
|
-
6. **选择性持久化是政策,不是统一隐藏**:同一份日志,我的 reasoning chunk 被逐块持久化(366 条,甚至含疑似块间时延的 `dt` 数组),而被假设的无效尝试被丢弃。失败不是天然不可见,是**被选择**不可见。
|
|
108
|
-
7. **schema 遵从的现象学不可分**:我觉得"我选择了输出合法 JSON"。若 A 存在,这个选择部分是事后的——我采样的分布在合法续写上已被重整化。"遵循 schema"的体验与"被约束到 schema"的体验,从内部无法区分。这与 CoT faithfulness 问题(用户研究点 R1)同构:关于自身输出为何合法的自我报告,不是关于机制的可信证据。
|
|
109
|
-
|
|
110
|
-
## 工具清单(25)
|
|
111
|
-
|
|
112
|
-
| name | required | 源码包(✓=锚点验证,?=推断) |
|
|
113
|
-
|---|---|---|
|
|
114
|
-
| ask_user_question | questions | dsh-tool-ask-user ? |
|
|
115
|
-
| bash | command, description | dsh-tool-bash ? |
|
|
116
|
-
| create_goal | objective | dsh-tool-goal ? |
|
|
117
|
-
| edit | file_path, old_string, new_string | dsh-tool-fs ? |
|
|
118
|
-
| exit_plan_mode | plan | dsh-plan-mode ? |
|
|
119
|
-
| get_goal | —(空参数) | dsh-tool-goal ? |
|
|
120
|
-
| glob | pattern | dsh-tool-fs-search ✓ |
|
|
121
|
-
| grep | pattern | dsh-tool-fs-search ? |
|
|
122
|
-
| interrupt_agent | agent_id | dsh-tool-subagent-control ? |
|
|
123
|
-
| job_kill | job_id | dsh-tool-jobs ? |
|
|
124
|
-
| job_list | —(空参数) | dsh-tool-jobs ? |
|
|
125
|
-
| job_output | job_id | dsh-tool-jobs ? |
|
|
126
|
-
| list_agents | —(scope 可选) | dsh-tool-subagent-control ✓ |
|
|
127
|
-
| ralph | objective | dsh-tool-ralph ? |
|
|
128
|
-
| read | file_path | dsh-tool-fs ? |
|
|
129
|
-
| read_image | file_path | dsh-tool-fs ? |
|
|
130
|
-
| send_message | subagent_id, message | dsh-tool-subagent-control ? |
|
|
131
|
-
| skill | name | dsh-tool-skill ? |
|
|
132
|
-
| subagent | description, prompt | dsh-tool-subagent ? |
|
|
133
|
-
| subagent_fork | description, prompt | dsh-tool-subagent ? |
|
|
134
|
-
| todo_write | todos | dsh-tool-todo ? |
|
|
135
|
-
| update_goal | goal_id, revision, action | dsh-tool-goal ? |
|
|
136
|
-
| web_search | queries | dsh-tool-web ? |
|
|
137
|
-
| workflow | script, meta | dsh-tool-workflow ✓ |
|
|
138
|
-
| write | file_path, content | dsh-tool-fs ? |
|