@sema-agent/client-core 0.2.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/README.md +112 -0
- package/dist/adapt.d.ts +66 -0
- package/dist/adapt.js +773 -0
- package/dist/diagnostics.d.ts +37 -0
- package/dist/diagnostics.js +29 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +15 -0
- package/dist/notifications.d.ts +55 -0
- package/dist/notifications.js +97 -0
- package/dist/retryStatus.d.ts +36 -0
- package/dist/retryStatus.js +28 -0
- package/dist/seam.d.ts +187 -0
- package/dist/seam.js +13 -0
- package/dist/steering.d.ts +61 -0
- package/dist/steering.js +103 -0
- package/dist/workflow.d.ts +18 -0
- package/dist/workflow.js +60 -0
- package/package.json +30 -0
package/dist/steering.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* steering.ts — `steering_injected` → renderable attachment projection (PURE)。
|
|
3
|
+
* cli src/sema/steeringAttachments.ts 的逐字搬运(#52a;差分守卫钉两侧等价)。
|
|
4
|
+
*
|
|
5
|
+
* core 1.251 (design/133, board [479] ask-1) echoes every engine-side SYSTEM steering injection as a
|
|
6
|
+
* `steering_injected` wire event `{source, preview}` — `preview` = the injected body's first 220 chars
|
|
7
|
+
* (runtask.ts:2320), echo-only (the model-facing message is unchanged). Sources today:
|
|
8
|
+
* `deadline_nudge` / `finalize` (TB telemetry B3) and the design/133 turn-boundary attachment
|
|
9
|
+
* producers `todo_reminder` / `task_reminder` / `changed_files` / `plan_mode`, plus the G1 [482]
|
|
10
|
+
* members `background_tasks` / `tools_delta` (core 1.253).
|
|
11
|
+
*
|
|
12
|
+
* [479] ask-1 contract: a renderer that branches on `source` MUST carry a default arm — core may add
|
|
13
|
+
* sources without a cross-repo lockstep. This mapper is that branch point: known sources get their
|
|
14
|
+
* copy (the 四值文案), everything else falls to the generic default row (never dropped, never a
|
|
15
|
+
* crash). PURE (no env/IO) so it unit-tests without the render graph — the wireCaps pattern.
|
|
16
|
+
*
|
|
17
|
+
* Render policy (CC 2.1.198 parity): CC NULL-renders its own turn-boundary reminders
|
|
18
|
+
* (`todo_reminder` / `task_reminder` / `plan_mode` are in NULL_RENDERING_TYPES — the user never sees
|
|
19
|
+
* them in the normal transcript). The projected `steering_injected` attachment therefore renders
|
|
20
|
+
* ONLY in transcript (ctrl+o) / verbose mode (AttachmentMessage arm) — normal-mode output stays
|
|
21
|
+
* byte-identical to CC, while sema's two-process split keeps engine-side injections observable.
|
|
22
|
+
*/
|
|
23
|
+
/** Per-source display copy. [479] ask-1 四值 + the pre-existing TB sources. Open set — an unknown
|
|
24
|
+
* source falls to the default label (never dropped). */
|
|
25
|
+
const SOURCE_LABELS = {
|
|
26
|
+
todo_reminder: 'Todo list reminder re-surfaced to the model',
|
|
27
|
+
task_reminder: 'Task list reminder re-surfaced to the model',
|
|
28
|
+
changed_files: 'Externally modified files flagged to the model (re-read before editing)',
|
|
29
|
+
plan_mode: 'Plan mode constraint re-surfaced to the model',
|
|
30
|
+
deadline_nudge: 'Deadline nudge injected',
|
|
31
|
+
finalize: 'Finalize instruction injected',
|
|
32
|
+
// G1 [482]/[487]② — background_tasks normally projects to VISIBLE task_status rows below; this
|
|
33
|
+
// label is its parse-failure fallback (clipped-beyond-recognition preview) + the tools_delta row.
|
|
34
|
+
background_tasks: 'Background tasks from before compaction announced to the model',
|
|
35
|
+
tools_delta: 'Newly available tools announced to the model',
|
|
36
|
+
};
|
|
37
|
+
/** Default-arm label for a source this shell build predates. */
|
|
38
|
+
export function steeringLabel(source) {
|
|
39
|
+
return SOURCE_LABELS[source] ?? `Steering injected (${source})`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* core turn-attachments.ts renderBackgroundTasks line shape (198 vbl VERBATIM phrases):
|
|
43
|
+
* `- [${task_id}] Task "${description}" ${phrase}`
|
|
44
|
+
* phrase: completed → "completed in background" · killed → "stopped" · running → "still running in
|
|
45
|
+
* background" · anything else → the raw status word (core's own fallback arm). The wire preview is
|
|
46
|
+
* clipped at 220 chars, so the LAST line may be cut — a non-matching line is skipped, never fails
|
|
47
|
+
* the batch.
|
|
48
|
+
*/
|
|
49
|
+
const PHRASE_TO_STATUS = [
|
|
50
|
+
['completed in background', 'completed'],
|
|
51
|
+
['still running in background', 'running'],
|
|
52
|
+
['stopped', 'killed'],
|
|
53
|
+
// core's raw-status fallback arm for the non-vbl states (announce snapshots pending/running, but
|
|
54
|
+
// parse defensively — a settle can race the boundary).
|
|
55
|
+
['pending', 'pending'],
|
|
56
|
+
['running', 'running'],
|
|
57
|
+
['completed', 'completed'],
|
|
58
|
+
['failed', 'failed'],
|
|
59
|
+
['killed', 'killed'],
|
|
60
|
+
];
|
|
61
|
+
function parseBackgroundTaskLine(line) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
for (const [phrase, status] of PHRASE_TO_STATUS) {
|
|
64
|
+
const suffix = `" ${phrase}`;
|
|
65
|
+
if (!trimmed.endsWith(suffix))
|
|
66
|
+
continue;
|
|
67
|
+
const head = trimmed.slice(0, trimmed.length - suffix.length);
|
|
68
|
+
const m = /^- \[([^\]]+)\] Task "([\s\S]*)$/.exec(head);
|
|
69
|
+
if (!m)
|
|
70
|
+
return null;
|
|
71
|
+
return {
|
|
72
|
+
type: 'task_status',
|
|
73
|
+
taskId: m[1],
|
|
74
|
+
taskType: 'local_bash',
|
|
75
|
+
status,
|
|
76
|
+
description: m[2],
|
|
77
|
+
deltaSummary: null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Project one `steering_injected` wire event into its renderable attachment(s). Always returns at
|
|
84
|
+
* least one attachment (default 兜底) — an engine injection is never silently invisible in
|
|
85
|
+
* transcript mode, whatever the source.
|
|
86
|
+
*
|
|
87
|
+
* `background_tasks` ([487]② G1): the preview lines parse into CC `task_status` attachments — the
|
|
88
|
+
* SAME (VISIBLE) GenericTaskStatus/vbl rendering the LOCAL post-compact path uses, three-state copy
|
|
89
|
+
* 198 verbatim, `[task_id]` addressable via TaskOutput/TaskStop. A preview clipped beyond
|
|
90
|
+
* recognition falls back to the generic (transcript-only) row — never invisible, never a crash.
|
|
91
|
+
*/
|
|
92
|
+
export function steeringInjectedToAttachments(source, preview) {
|
|
93
|
+
if (source === 'background_tasks') {
|
|
94
|
+
const tasks = preview
|
|
95
|
+
.split('\n')
|
|
96
|
+
.map(parseBackgroundTaskLine)
|
|
97
|
+
.filter((t) => t !== null);
|
|
98
|
+
if (tasks.length > 0)
|
|
99
|
+
return tasks;
|
|
100
|
+
// fall through: clipped/unrecognized body → generic row (default 兜底)
|
|
101
|
+
}
|
|
102
|
+
return [{ type: 'steering_injected', source, label: steeringLabel(source), preview }];
|
|
103
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workflow 车道纯函数(抽自 sema-cli footerRowBelt/workflowTaskOutputProjection,围栏见
|
|
3
|
+
* cli 仓 frameLaneGuards/taskOutputWorkflowEnvelope 套;[1617] 幽灵行家族的判别资产)。
|
|
4
|
+
*/
|
|
5
|
+
/** core 1.356 BCE 合成 workflow-agent id 形:wa+16hex。
|
|
6
|
+
* 真实 fleet 子行 id 是 `${runId} ${engineTaskId}` 复合形——必须取空白分隔尾段再匹配
|
|
7
|
+
* (cli footerRowBelt 原版语义;codex 对抗复审抓的等价性破坏,0.1.1 修)。 */
|
|
8
|
+
export declare function isWorkflowAgentTaskId(taskId: string): boolean;
|
|
9
|
+
/** TaskOutput workflow 轮询信封识别(core task-registry formatWorkflowRun 真形:
|
|
10
|
+
* {task_id, type:"workflow", status, name?, …};type+task_id 双门,非该形返回 null)。 */
|
|
11
|
+
export declare function parseWorkflowPollEnvelope(body: string): {
|
|
12
|
+
taskId: string;
|
|
13
|
+
status: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
} | null;
|
|
16
|
+
/** workflow 轮询 JSON → 人话多行投影(agents 汇总行 + per-agent ✓/✗ 明细 + note/error 尾透传);
|
|
17
|
+
* 非 JSON 原样返回(fail-soft)。 */
|
|
18
|
+
export declare function projectWorkflowTaskOutput(jsonSrc: string): string;
|
package/dist/workflow.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workflow 车道纯函数(抽自 sema-cli footerRowBelt/workflowTaskOutputProjection,围栏见
|
|
3
|
+
* cli 仓 frameLaneGuards/taskOutputWorkflowEnvelope 套;[1617] 幽灵行家族的判别资产)。
|
|
4
|
+
*/
|
|
5
|
+
/** core 1.356 BCE 合成 workflow-agent id 形:wa+16hex。
|
|
6
|
+
* 真实 fleet 子行 id 是 `${runId} ${engineTaskId}` 复合形——必须取空白分隔尾段再匹配
|
|
7
|
+
* (cli footerRowBelt 原版语义;codex 对抗复审抓的等价性破坏,0.1.1 修)。 */
|
|
8
|
+
export function isWorkflowAgentTaskId(taskId) {
|
|
9
|
+
const tail = taskId.split(/\s+/).pop() ?? taskId;
|
|
10
|
+
return /^wa[0-9a-f]{16}$/.test(tail);
|
|
11
|
+
}
|
|
12
|
+
/** TaskOutput workflow 轮询信封识别(core task-registry formatWorkflowRun 真形:
|
|
13
|
+
* {task_id, type:"workflow", status, name?, …};type+task_id 双门,非该形返回 null)。 */
|
|
14
|
+
export function parseWorkflowPollEnvelope(body) {
|
|
15
|
+
try {
|
|
16
|
+
const j = JSON.parse(body);
|
|
17
|
+
if (j.type !== 'workflow' || typeof j.task_id !== 'string' || j.task_id.length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
return {
|
|
20
|
+
taskId: j.task_id,
|
|
21
|
+
status: typeof j.status === 'string' && j.status.length > 0 ? j.status : 'completed',
|
|
22
|
+
...(typeof j.name === 'string' && j.name.length > 0 ? { name: j.name } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** workflow 轮询 JSON → 人话多行投影(agents 汇总行 + per-agent ✓/✗ 明细 + note/error 尾透传);
|
|
30
|
+
* 非 JSON 原样返回(fail-soft)。 */
|
|
31
|
+
export function projectWorkflowTaskOutput(jsonSrc) {
|
|
32
|
+
try {
|
|
33
|
+
const j = JSON.parse(jsonSrc);
|
|
34
|
+
const parts = [];
|
|
35
|
+
if (j.agents && typeof j.agents.done === 'number' && typeof j.agents.total === 'number') {
|
|
36
|
+
parts.push(`agents: ${j.agents.done}/${j.agents.total} done${typeof j.agents.failed === 'number' && j.agents.failed > 0 ? ` (${j.agents.failed} failed)` : ''}`);
|
|
37
|
+
}
|
|
38
|
+
if (Array.isArray(j.agent_runs)) {
|
|
39
|
+
for (const r of j.agent_runs) {
|
|
40
|
+
if (!r || typeof r !== 'object')
|
|
41
|
+
continue;
|
|
42
|
+
const label = typeof r.label === 'string' && r.label.length > 0 ? r.label : '(agent)';
|
|
43
|
+
const st = typeof r.status === 'string' ? r.status : '?';
|
|
44
|
+
const errLine = typeof r.error === 'string' && r.error.length > 0 ? ` — ${r.error.split('\n')[0].slice(0, 120)}` : '';
|
|
45
|
+
const outLine = !errLine && typeof r.output === 'string' && r.output.length > 0
|
|
46
|
+
? ` — ${r.output.split('\n')[0].slice(0, 80)}`
|
|
47
|
+
: '';
|
|
48
|
+
parts.push(` ${st === 'completed' ? '✓' : st === 'failed' ? '✗' : '·'} ${label} [${st}]${errLine}${outLine}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (typeof j.note === 'string' && j.note.length > 0)
|
|
52
|
+
parts.push(j.note);
|
|
53
|
+
if (typeof j.error === 'string' && j.error.length > 0)
|
|
54
|
+
parts.push(j.error);
|
|
55
|
+
return parts.join('\n');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return jsonSrc;
|
|
59
|
+
}
|
|
60
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sema-agent/client-core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Blackboard [1832] design axioms; [1651]/[1652]/[1653] signed seam design. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"repository": "github:sema-agent/sema-client-core",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"test": "node scripts/run-client-core-pure-test.mjs && node scripts/run-client-core-diff-test.mjs"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@sema-agent/agent-types": ">=0.2.0",
|
|
22
|
+
"@sema-agent/sdk": ">=0.0.100"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@sema-agent/agent-types": "^0.2.0",
|
|
26
|
+
"@sema-agent/sdk": "^0.0.106",
|
|
27
|
+
"esbuild": "^0.27.4",
|
|
28
|
+
"typescript": "^6.0.2"
|
|
29
|
+
}
|
|
30
|
+
}
|