@agent-compose/sdk 0.7.0 → 0.8.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.
Files changed (116) hide show
  1. package/README.md +66 -39
  2. package/dist/agent/__tests__/runtime-json-schema.test.d.ts +10 -0
  3. package/dist/agent/agent-context.d.ts +21 -1
  4. package/dist/agent/agent-loop.d.ts +24 -1
  5. package/dist/client.d.ts +338 -534
  6. package/dist/directives.d.ts +112 -0
  7. package/dist/display.d.ts +242 -0
  8. package/dist/errors.d.ts +24 -1
  9. package/dist/index.d.ts +24 -12
  10. package/dist/index.js +3545 -1667
  11. package/dist/pause/wrappers.d.ts +31 -9
  12. package/dist/runtimes/_acp-client.d.ts +46 -1
  13. package/dist/runtimes/_cli-agent.d.ts +49 -4
  14. package/dist/runtimes/_jsonl-guard.d.ts +103 -0
  15. package/dist/runtimes/amp.d.ts +2 -2
  16. package/dist/runtimes/claude-code.d.ts +59 -0
  17. package/dist/runtimes/claude-code.test.d.ts +14 -0
  18. package/dist/runtimes/claude.d.ts +16 -0
  19. package/dist/runtimes/claude.test.d.ts +8 -0
  20. package/dist/runtimes/codex.d.ts +9 -3
  21. package/dist/runtimes/cursor.d.ts +2 -2
  22. package/dist/runtimes/droid.d.ts +2 -2
  23. package/dist/runtimes/jsonl-guard.test.d.ts +19 -0
  24. package/dist/runtimes/openai-desktop.js +2691 -864
  25. package/dist/runtimes/opencode.d.ts +2 -2
  26. package/dist/runtimes/vercel.js +12 -1
  27. package/dist/sandbox/devbox.d.ts +42 -0
  28. package/dist/sandbox/exec-stream.d.ts +14 -0
  29. package/dist/sandbox/network-policy.d.ts +100 -0
  30. package/dist/sandbox/provider-def.d.ts +79 -0
  31. package/dist/sandbox/providers/desktop.d.ts +10 -0
  32. package/dist/sandbox/providers/e2b.d.ts +17 -0
  33. package/dist/sandbox/providers/local.d.ts +11 -0
  34. package/dist/sandbox/providers/vercel.d.ts +18 -0
  35. package/dist/sandbox/registry.d.ts +45 -0
  36. package/dist/sandbox/sizes.d.ts +68 -0
  37. package/dist/sandbox.d.ts +24 -299
  38. package/dist/step-invocation/__tests__/foreground-recovery.test.d.ts +1 -0
  39. package/dist/step-invocation/invoker.d.ts +10 -0
  40. package/dist/step-invocation/protocol.d.ts +5 -0
  41. package/dist/types/api-compliance.d.ts +71 -0
  42. package/dist/types/api-conversations.d.ts +492 -0
  43. package/dist/types/api-factory.d.ts +309 -0
  44. package/dist/types/api-projects.d.ts +131 -0
  45. package/dist/types/api-runs.d.ts +377 -0
  46. package/dist/types/api-scopes.d.ts +102 -0
  47. package/dist/types/conversation-stream.d.ts +191 -0
  48. package/dist/types/execution-context.d.ts +12 -2
  49. package/dist/types/protocol.d.ts +30 -1
  50. package/dist/types/sandbox-environment.d.ts +8 -5
  51. package/dist/types/sandbox.d.ts +74 -4
  52. package/dist/types/workflow-metadata.d.ts +33 -8
  53. package/dist/types/workflow-plan.d.ts +10 -0
  54. package/dist/types/workflow.d.ts +18 -205
  55. package/dist/utils/bundler.d.ts +12 -1
  56. package/dist/workflow-steps/index.d.ts +1 -1
  57. package/dist/workflow-steps/observability.d.ts +8 -1
  58. package/dist/workflow-steps/runner.d.ts +3 -3
  59. package/dist/workflow-steps/step.d.ts +15 -1
  60. package/dist/workflow-steps/types.d.ts +19 -5
  61. package/dist/workflow-steps/workflow.d.ts +22 -1
  62. package/dist/workflows/engine.d.ts +3 -2
  63. package/dist/workflows/invoke-child.d.ts +2 -2
  64. package/package.json +1 -1
  65. package/src/agent/agent-context.ts +186 -3
  66. package/src/agent/agent-loop.ts +31 -2
  67. package/src/client.ts +909 -621
  68. package/src/directives.ts +184 -0
  69. package/src/display.ts +788 -0
  70. package/src/errors.ts +39 -0
  71. package/src/index.ts +104 -10
  72. package/src/pause/wrappers.ts +44 -9
  73. package/src/runtimes/_acp-client.ts +72 -3
  74. package/src/runtimes/_cli-agent.ts +159 -36
  75. package/src/runtimes/_jsonl-guard.ts +219 -0
  76. package/src/runtimes/claude-code.ts +246 -0
  77. package/src/runtimes/claude.ts +32 -2
  78. package/src/runtimes/codex.ts +55 -3
  79. package/src/runtimes/openai-desktop.ts +59 -14
  80. package/src/sandbox/devbox.ts +48 -0
  81. package/src/sandbox/exec-stream.ts +48 -0
  82. package/src/sandbox/network-policy.ts +181 -0
  83. package/src/sandbox/provider-def.ts +94 -0
  84. package/src/sandbox/providers/desktop.ts +57 -0
  85. package/src/sandbox/providers/e2b.ts +354 -0
  86. package/src/sandbox/providers/local.ts +106 -0
  87. package/src/sandbox/providers/vercel.ts +331 -0
  88. package/src/sandbox/registry.ts +198 -0
  89. package/src/sandbox/sizes.ts +95 -0
  90. package/src/sandbox.ts +59 -1275
  91. package/src/step-invocation/invoker.ts +151 -28
  92. package/src/step-invocation/protocol.ts +8 -0
  93. package/src/types/api-compliance.ts +79 -0
  94. package/src/types/api-conversations.ts +522 -0
  95. package/src/types/api-factory.ts +336 -0
  96. package/src/types/api-projects.ts +140 -0
  97. package/src/types/api-runs.ts +412 -0
  98. package/src/types/api-scopes.ts +102 -0
  99. package/src/types/conversation-stream.ts +231 -0
  100. package/src/types/execution-context.ts +10 -2
  101. package/src/types/protocol.ts +33 -0
  102. package/src/types/sandbox-environment.ts +28 -9
  103. package/src/types/sandbox.ts +73 -4
  104. package/src/types/workflow-metadata.ts +35 -8
  105. package/src/types/workflow-plan.ts +11 -0
  106. package/src/types/workflow.ts +25 -292
  107. package/src/utils/bundler.ts +32 -5
  108. package/src/utils/errors.ts +16 -1
  109. package/src/workflow-steps/index.ts +1 -0
  110. package/src/workflow-steps/observability.ts +19 -8
  111. package/src/workflow-steps/runner.ts +4 -4
  112. package/src/workflow-steps/step.ts +49 -1
  113. package/src/workflow-steps/types.ts +20 -5
  114. package/src/workflow-steps/workflow.ts +22 -1
  115. package/src/workflows/engine.ts +3 -2
  116. package/src/workflows/invoke-child.ts +2 -2
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Cloud-session UI directives — the typed marker contract between the
3
+ * `agentc` CLI running INSIDE a cloud session's sandbox and the server's
4
+ * cloud executor.
5
+ *
6
+ * A converged cloud session drives a coding CLI whose only platform surface
7
+ * is `agentc` invoked over Bash — it has no typed platform tools, so it
8
+ * could never produce the transcript parts the dashboard renders as rich
9
+ * cards (`get_run_changes` → the inline diff reviewer) or acts on
10
+ * (`navigate_dashboard` → armed-tab navigation). The bridge:
11
+ *
12
+ * 1. `agentc navigate|display …` PRINTS one marker line to stdout —
13
+ * `[[ac:directive:v1 {"kind":…}]]` — and nothing else happens locally.
14
+ * 2. The marker rides back to the server inside the streamed tool_result
15
+ * (the coding CLI echoes the command's output).
16
+ * 3. The cloud executor scans TOOL RESULTS (never model text) for
17
+ * markers, executes each directive server-side through the SAME
18
+ * platform tool executors a platform turn uses (validation, factory
19
+ * gating, result shapes all identical), and persists the resulting
20
+ * tool_call + tool_result pair into the transcript.
21
+ * 4. Existing consumers act unchanged: the dashboard's diff-card /
22
+ * run-card renderers key on tool names, and navigation stays gated by
23
+ * the requesting tab's armed window + client-side URL re-validation.
24
+ *
25
+ * The kind set is CLOSED, but no longer purely read-only. `ask` is the ONE
26
+ * write-bearing directive: it inserts a bounded mentions row as the session
27
+ * owner (who could ping the same member from the dashboard anyway) and
28
+ * persists an ask card. Everything else stays read-scope — run lookups,
29
+ * change-set listing, server-gated file reads (preview / table_file /
30
+ * file_diff), or the navigate directive (validated URL, acted on
31
+ * client-side, cannot submit anything). Markers are data in untrusted
32
+ * output — the parser is hostile-input safe and hard-capped.
33
+ */
34
+
35
+ /** Marker frame. v1 is part of the prefix: unknown future versions parse
36
+ * as no-match (fail closed) rather than as a v1 directive. */
37
+ export const DIRECTIVE_MARKER_PREFIX = "[[ac:directive:v1 ";
38
+ export const DIRECTIVE_MARKER_SUFFIX = "]]";
39
+
40
+ /** Max directives honoured per tool result — one command emits one marker;
41
+ * anything past this in a single output is echo/noise, not intent. */
42
+ export const MAX_DIRECTIVES_PER_OUTPUT = 4;
43
+
44
+ export type CloudDirective =
45
+ /** Take the requesting user's dashboard tab to a relative page. */
46
+ | { kind: "navigate"; url: string }
47
+ /** Render one run's detail into the transcript (`get_run` shape). */
48
+ | { kind: "run"; runId: string; workflow?: string }
49
+ /** Render one run's change-set — the dashboard's inline diff reviewer
50
+ * (`get_run_changes` shape). */
51
+ | { kind: "run_changes"; runId: string; workflow?: string }
52
+ /** Sandboxed inline HTML preview of a drive file, frozen (and size-capped)
53
+ * server-side at display time (`display_preview` shape). */
54
+ | { kind: "preview"; path: string }
55
+ /** Sortable table card sourced from a drive .csv/.json file, read and
56
+ * capped server-side (`display_table` shape). */
57
+ | { kind: "table_file"; path: string }
58
+ /** File-level revision diff card; selectors resolve against
59
+ * `factory_file_revisions` server-side (`display_diff` shape). */
60
+ | { kind: "file_diff"; path: string; from: string; to: string }
61
+ /** Interactive question card gated on a named approver — resolution and
62
+ * the mentions ping are server-authoritative (`display_ask` shape). The
63
+ * one write-bearing directive (see the module header). */
64
+ | { kind: "ask"; prompt: string; approver: string; options?: Array<{ id: string; label: string }> };
65
+
66
+ /** `runId` values the run directives accept: a UUID, or the literal
67
+ * `latest` (resolved server-side against the session's factory, optionally
68
+ * narrowed by `workflow`). */
69
+ const RUN_ID_RE = /^(latest|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
70
+
71
+ /** Revision selectors the `file_diff` directive accepts: a literal
72
+ * `factory_file_revisions.id`, `head`, `prev`, or `head~N` (N ≤ 999).
73
+ * Exported so the CLI validates with the same rule it emits under. */
74
+ export const REVISION_SELECTOR_RE = /^(\d{1,12}|head|prev|head~[1-9]\d{0,2})$/;
75
+
76
+ /** Drive-path bound shared by the path-bearing directive kinds. */
77
+ const DIRECTIVE_PATH_MAX = 512;
78
+
79
+ /** Ask directive bounds — tighter than the promoter-path ask marker, sized
80
+ * to fit the 1024-char directive body. */
81
+ export const ASK_DIRECTIVE_PROMPT_MAX = 500;
82
+ export const ASK_DIRECTIVE_MAX_OPTIONS = 6;
83
+ export const ASK_DIRECTIVE_OPTION_ID_MAX = 50;
84
+ export const ASK_DIRECTIVE_OPTION_LABEL_MAX = 60;
85
+ export const ASK_APPROVER_MIN = 3;
86
+ export const ASK_APPROVER_MAX = 320;
87
+
88
+ function validDirectivePath(v: unknown): string | null {
89
+ return typeof v === "string" && v.length >= 1 && v.length <= DIRECTIVE_PATH_MAX ? v : null;
90
+ }
91
+
92
+ /** One marker line for `agentc` to print. */
93
+ export function renderDirectiveMarker(directive: CloudDirective): string {
94
+ return `${DIRECTIVE_MARKER_PREFIX}${JSON.stringify(directive)}${DIRECTIVE_MARKER_SUFFIX}`;
95
+ }
96
+
97
+ function validDirective(value: unknown): CloudDirective | null {
98
+ if (typeof value !== "object" || value === null) return null;
99
+ const d = value as Record<string, unknown>;
100
+ if (d.kind === "navigate") {
101
+ const url = d.url;
102
+ if (typeof url !== "string" || url.length === 0 || url.length > 400) return null;
103
+ // Relative-only at the contract layer; the navigate tool re-validates
104
+ // against the site map and the dashboard validates a third time.
105
+ if (!url.startsWith("/") || url.startsWith("//")) return null;
106
+ return { kind: "navigate", url };
107
+ }
108
+ if (d.kind === "run" || d.kind === "run_changes") {
109
+ const runId = d.runId;
110
+ if (typeof runId !== "string" || !RUN_ID_RE.test(runId)) return null;
111
+ const workflow = d.workflow;
112
+ if (workflow !== undefined && (typeof workflow !== "string" || workflow.length === 0 || workflow.length > 255)) {
113
+ return null;
114
+ }
115
+ return { kind: d.kind, runId, ...(workflow !== undefined ? { workflow } : {}) };
116
+ }
117
+ if (d.kind === "preview" || d.kind === "table_file") {
118
+ const path = validDirectivePath(d.path);
119
+ if (!path) return null;
120
+ if (d.kind === "table_file" && !/\.(csv|json)$/i.test(path)) return null;
121
+ return { kind: d.kind, path };
122
+ }
123
+ if (d.kind === "file_diff") {
124
+ const path = validDirectivePath(d.path);
125
+ if (!path) return null;
126
+ const { from, to } = d;
127
+ if (typeof from !== "string" || !REVISION_SELECTOR_RE.test(from)) return null;
128
+ if (typeof to !== "string" || !REVISION_SELECTOR_RE.test(to)) return null;
129
+ return { kind: "file_diff", path, from, to };
130
+ }
131
+ if (d.kind === "ask") {
132
+ const { prompt, approver } = d;
133
+ if (typeof prompt !== "string" || prompt.length < 1 || prompt.length > ASK_DIRECTIVE_PROMPT_MAX) return null;
134
+ if (typeof approver !== "string" || approver.length < ASK_APPROVER_MIN || approver.length > ASK_APPROVER_MAX) {
135
+ return null;
136
+ }
137
+ let options: Array<{ id: string; label: string }> | undefined;
138
+ if (d.options !== undefined) {
139
+ if (!Array.isArray(d.options) || d.options.length === 0 || d.options.length > ASK_DIRECTIVE_MAX_OPTIONS) {
140
+ return null;
141
+ }
142
+ options = [];
143
+ for (const raw of d.options) {
144
+ if (typeof raw !== "object" || raw === null) return null;
145
+ const { id, label } = raw as { id?: unknown; label?: unknown };
146
+ if (typeof id !== "string" || id.length < 1 || id.length > ASK_DIRECTIVE_OPTION_ID_MAX) return null;
147
+ if (typeof label !== "string" || label.length < 1 || label.length > ASK_DIRECTIVE_OPTION_LABEL_MAX) {
148
+ return null;
149
+ }
150
+ options.push({ id, label });
151
+ }
152
+ }
153
+ return { kind: "ask", prompt, approver, ...(options !== undefined ? { options } : {}) };
154
+ }
155
+ return null;
156
+ }
157
+
158
+ /**
159
+ * Extract every valid v1 directive from one command output. Hostile-input
160
+ * safe: malformed JSON, unknown kinds, oversized fields, and unterminated
161
+ * markers are skipped silently; at most MAX_DIRECTIVES_PER_OUTPUT come
162
+ * back. Never throws.
163
+ */
164
+ export function parseDirectiveMarkers(text: string): CloudDirective[] {
165
+ const out: CloudDirective[] = [];
166
+ let from = 0;
167
+ while (out.length < MAX_DIRECTIVES_PER_OUTPUT) {
168
+ const start = text.indexOf(DIRECTIVE_MARKER_PREFIX, from);
169
+ if (start < 0) break;
170
+ const bodyStart = start + DIRECTIVE_MARKER_PREFIX.length;
171
+ const end = text.indexOf(DIRECTIVE_MARKER_SUFFIX, bodyStart);
172
+ if (end < 0) break;
173
+ from = end + DIRECTIVE_MARKER_SUFFIX.length;
174
+ const body = text.slice(bodyStart, end);
175
+ if (body.length > 1_024) continue;
176
+ try {
177
+ const directive = validDirective(JSON.parse(body));
178
+ if (directive) out.push(directive);
179
+ } catch {
180
+ // malformed JSON in a marker frame — echo/noise, skip
181
+ }
182
+ }
183
+ return out;
184
+ }