@zq-silk/yui 2.0.0 → 2.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.
Files changed (138) hide show
  1. package/README.md +4 -0
  2. package/dist/cli/commandCatalog.js +318 -289
  3. package/dist/cli/commandDiscovery.js +72 -0
  4. package/dist/cli/completion.js +22 -227
  5. package/dist/cli/dynamicCompletion.js +12 -6
  6. package/dist/cli/invocationAuthority.js +2 -2
  7. package/dist/cli/invocationRouter.js +18 -7
  8. package/dist/cli.js +23 -3030
  9. package/dist/commands/capabilityCommands.js +5 -5
  10. package/dist/commands/globalRoleCommands.js +2 -1
  11. package/dist/commands/taskCommands.js +90 -21
  12. package/dist/commands/taskIntegrationCommands.js +3 -1
  13. package/dist/commands/taskUpstreamCommands.js +3 -1
  14. package/dist/context/runContextPack.js +132 -5
  15. package/dist/context/sourceRunContext.js +4 -2
  16. package/dist/context/taskContext.js +12 -3
  17. package/dist/controlPlaneCli.js +3092 -0
  18. package/dist/controller/fileSchedulerStoreAdapter.js +19 -6
  19. package/dist/controller/jobControl.js +21 -0
  20. package/dist/executor/agentExecutor.js +1 -1
  21. package/dist/executor/effectiveLaunch.js +18 -5
  22. package/dist/executor/fileRoleLaunchPlanner.js +15 -19
  23. package/dist/integration/gitIntegrationService.js +50 -15
  24. package/dist/kernel/accessAssessment.js +1 -0
  25. package/dist/kernel/builtinCapabilities.js +28 -1
  26. package/dist/kernel/capabilityRegistry.js +64 -19
  27. package/dist/message/messageContinuation.js +7 -2
  28. package/dist/nativeAgent/agent.js +275 -0
  29. package/dist/nativeAgent/cliDemo.js +37 -0
  30. package/dist/nativeAgent/codingTools.js +11 -0
  31. package/dist/nativeAgent/commandTool.js +215 -0
  32. package/dist/nativeAgent/compactionDemo.js +158 -0
  33. package/dist/nativeAgent/composition.js +71 -0
  34. package/dist/nativeAgent/context/budget.js +44 -0
  35. package/dist/nativeAgent/context/index.js +339 -0
  36. package/dist/nativeAgent/context/providerCompressor.js +103 -0
  37. package/dist/nativeAgent/contracts.js +1 -0
  38. package/dist/nativeAgent/demo.js +40 -0
  39. package/dist/nativeAgent/evaluation/cases.js +38 -0
  40. package/dist/nativeAgent/evaluation/checks.js +91 -0
  41. package/dist/nativeAgent/evaluation/demo.js +19 -0
  42. package/dist/nativeAgent/evaluation/files.js +54 -0
  43. package/dist/nativeAgent/evaluation/fixture.js +36 -0
  44. package/dist/nativeAgent/evaluation/index.js +239 -0
  45. package/dist/nativeAgent/executionOwner.js +209 -0
  46. package/dist/nativeAgent/filePatterns.js +170 -0
  47. package/dist/nativeAgent/fileToolsSupport.js +202 -0
  48. package/dist/nativeAgent/index.js +16 -0
  49. package/dist/nativeAgent/interaction/cli.js +358 -0
  50. package/dist/nativeAgent/interaction/contracts.js +1 -0
  51. package/dist/nativeAgent/interaction/index.js +3 -0
  52. package/dist/nativeAgent/interaction/memoryDemo.js +115 -0
  53. package/dist/nativeAgent/interaction/renderer.js +34 -0
  54. package/dist/nativeAgent/localSafety.js +258 -0
  55. package/dist/nativeAgent/mockProvider.js +43 -0
  56. package/dist/nativeAgent/model/anthropicMessages.js +204 -0
  57. package/dist/nativeAgent/model/chatCompletions.js +210 -0
  58. package/dist/nativeAgent/model/errors.js +47 -0
  59. package/dist/nativeAgent/model/gateway.js +423 -0
  60. package/dist/nativeAgent/model/index.js +7 -0
  61. package/dist/nativeAgent/model/observationAdapter.js +21 -0
  62. package/dist/nativeAgent/model/protocols.js +19 -0
  63. package/dist/nativeAgent/model/responses.js +263 -0
  64. package/dist/nativeAgent/model/types.js +1 -0
  65. package/dist/nativeAgent/model/wire.js +73 -0
  66. package/dist/nativeAgent/observability/index.js +220 -0
  67. package/dist/nativeAgent/product/catalog.js +82 -0
  68. package/dist/nativeAgent/product/config.js +295 -0
  69. package/dist/nativeAgent/product/facts.js +30 -0
  70. package/dist/nativeAgent/product/index.js +62 -0
  71. package/dist/nativeAgent/product/location.js +44 -0
  72. package/dist/nativeAgent/product/runtime.js +276 -0
  73. package/dist/nativeAgent/product/storage.js +49 -0
  74. package/dist/nativeAgent/product/tools.js +47 -0
  75. package/dist/nativeAgent/product/transport.js +54 -0
  76. package/dist/nativeAgent/projectGuidance/index.js +425 -0
  77. package/dist/nativeAgent/searchTools.js +305 -0
  78. package/dist/nativeAgent/session/backends.js +293 -0
  79. package/dist/nativeAgent/session/catalog.js +97 -0
  80. package/dist/nativeAgent/session/catalogDemo.js +87 -0
  81. package/dist/nativeAgent/session/contracts.js +1 -0
  82. package/dist/nativeAgent/session/format.js +269 -0
  83. package/dist/nativeAgent/session/index.js +5 -0
  84. package/dist/nativeAgent/session/location.js +36 -0
  85. package/dist/nativeAgent/session/sqliteFormat.js +134 -0
  86. package/dist/nativeAgent/session/store.js +248 -0
  87. package/dist/nativeAgent/textTools.js +293 -0
  88. package/dist/nativeAgent/toolManager/executor.js +290 -0
  89. package/dist/nativeAgent/toolManager/index.js +4 -0
  90. package/dist/nativeAgent/validation.js +95 -0
  91. package/dist/plugins/pluginService.js +98 -8
  92. package/dist/resources/projectResourceService.js +23 -1
  93. package/dist/runtime/managedIdentity.js +6 -0
  94. package/dist/surface/surfaceContributions.js +3 -0
  95. package/dist/task/taskAuthority.js +61 -10
  96. package/dist/web/assets/assetManifest.js +38 -22
  97. package/dist/web/assets/client/api.js +115 -0
  98. package/dist/web/assets/client/app.js +615 -862
  99. package/dist/web/assets/client/components.js +323 -897
  100. package/dist/web/assets/client/detail.js +333 -0
  101. package/dist/web/assets/client/dock.js +225 -0
  102. package/dist/web/assets/client/dom.js +55 -3
  103. package/dist/web/assets/client/evidence.js +172 -0
  104. package/dist/web/assets/client/format.js +25 -14
  105. package/dist/web/assets/client/forms.js +230 -0
  106. package/dist/web/assets/client/i18n.js +1024 -791
  107. package/dist/web/assets/client/overview.js +118 -0
  108. package/dist/web/assets/client/records.js +63 -0
  109. package/dist/web/assets/client/sections.js +313 -0
  110. package/dist/web/assets/client/sidebar.js +146 -0
  111. package/dist/web/assets/client/theme.js +61 -22
  112. package/dist/web/assets/icons.js +39 -0
  113. package/dist/web/assets/shell.js +125 -118
  114. package/dist/web/assets/styles/base.js +41 -0
  115. package/dist/web/assets/styles/components.js +169 -0
  116. package/dist/web/assets/styles/layout.js +56 -77
  117. package/dist/web/assets/styles/markdown.js +16 -24
  118. package/dist/web/assets/styles/responsive.js +41 -44
  119. package/dist/web/assets/styles/tokens.js +65 -89
  120. package/dist/web/assets/styles/views.js +292 -0
  121. package/dist/web/webServer.js +2 -1
  122. package/docs/agent-result-consumption.md +16 -0
  123. package/docs/agent-result-consumption.zh-CN.md +13 -0
  124. package/docs/examples/agent-offline.mjs +194 -0
  125. package/docs/native-agent.md +283 -0
  126. package/docs/release-workflow.md +61 -0
  127. package/docs/release-workflow.zh-CN.md +46 -0
  128. package/docs/roles-and-configuration.md +32 -0
  129. package/docs/roles-and-configuration.zh-CN.md +26 -0
  130. package/package.json +1 -1
  131. package/skills/yui-leader/SKILL.md +9 -0
  132. package/skills/yui-reviewer/SKILL.md +5 -0
  133. package/skills/yui-runtime/SKILL.md +33 -0
  134. package/dist/web/assets/client/taskSummary.js +0 -350
  135. package/dist/web/assets/client/taskSurface.js +0 -616
  136. package/dist/web/assets/client/view.js +0 -608
  137. package/dist/web/assets/styles/cards.js +0 -247
  138. package/dist/web/assets/styles/widgets.js +0 -168
@@ -1,5 +1,6 @@
1
+ import { hasManagedIdentity } from "../runtime/managedIdentity.js";
1
2
  import { usageError } from "../errors/cliError.js";
2
- import { MANAGED_NATIVE_SESSION_ENV, currentManagedRuntime } from "../runtime/managedCaller.js";
3
+ import { currentManagedRuntime } from "../runtime/managedCaller.js";
3
4
  const LEADER_ROLE = "leader";
4
5
  export function taskActor(environment, taskId) {
5
6
  const env = environment ?? {};
@@ -16,9 +17,7 @@ export function taskActor(environment, taskId) {
16
17
  return "operator";
17
18
  throw usageError("A managed global Session may perform this action only as Operator.");
18
19
  }
19
- if (env.YUI_ROLE !== undefined
20
- || env.YUI_AGENT_ID !== undefined
21
- || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
20
+ if (hasManagedIdentity(env)) {
22
21
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
23
22
  }
24
23
  return "user";
@@ -52,6 +51,62 @@ export function assertTaskDeliveryAuthority(store, environment, taskId) {
52
51
  }
53
52
  return actor;
54
53
  }
54
+ /** Project effects consume the current Session's captured scope, never the
55
+ * Role's desired configuration or the mere presence of a writable directory.
56
+ * Task management (including abort/inspection) remains a separate authority. */
57
+ export function assertTaskProjectWriteAuthority(store, environment, taskId, projectId) {
58
+ const actor = assertTaskDeliveryAuthority(store, environment, taskId);
59
+ if (actor !== "leader")
60
+ return actor;
61
+ const caller = currentManagedRuntime(store, environment, taskId, LEADER_ROLE);
62
+ const session = store.getTaskRoleSessionSet(taskId, LEADER_ROLE)?.sessions[caller.agentId];
63
+ const effective = session?.effective;
64
+ const task = store.getTask(taskId);
65
+ const main = store.getTaskWorkspace(taskId);
66
+ const entry = main?.entries.find(entry => entry.projectId === projectId);
67
+ if (task?.status !== "active" || task.executionGate.state !== "enabled"
68
+ || !task.projectBindings.some(binding => binding.projectId === projectId)
69
+ || effective?.profileAccess !== "write" || !effective.writeProjectIds.includes(projectId)
70
+ || main?.owner.type !== "task" || main.owner.taskId !== taskId
71
+ || effective.workspace.root !== main.root || entry?.access !== "write"
72
+ || !effective.workspace.entries.some(captured => captured.projectId === projectId
73
+ && captured.access === "write" && captured.path === entry.path)) {
74
+ throw usageError("Project write requires this Task's current delivery Session with a captured writable Project in its Task-main workspace. Read the Session scope; use formal Session replacement to adopt a new boundary.");
75
+ }
76
+ return actor;
77
+ }
78
+ /** A managed Leader integrates into its captured Task-main, not any branch
79
+ * reachable through the same Git repository. The executor also verifies that
80
+ * this ref is physically checked out here immediately before target effects. */
81
+ export function taskIntegrationTargetCheckout(store, environment, taskId, projectId, targetRef) {
82
+ if (assertTaskProjectWriteAuthority(store, environment, taskId, projectId) !== "leader") {
83
+ return undefined;
84
+ }
85
+ return taskIntegrationSettlementCheckout(store, environment, taskId, projectId, targetRef);
86
+ }
87
+ /** Confirming an already-applied CAS is Task management, not a Project write
88
+ * grant. Keep the current delivery identity and captured target ownership, but
89
+ * do not require or change its declared write scope. Never use this for CAS. */
90
+ export function taskIntegrationSettlementCheckout(store, environment, taskId, projectId, targetRef) {
91
+ if (assertTaskDeliveryAuthority(store, environment, taskId) !== "leader")
92
+ return undefined;
93
+ const task = store.getTask(taskId);
94
+ const main = store.getTaskWorkspace(taskId);
95
+ const entry = main?.entries.find(entry => entry.projectId === projectId);
96
+ const caller = currentManagedRuntime(store, environment, taskId, LEADER_ROLE);
97
+ const effective = store.getTaskRoleSessionSet(taskId, LEADER_ROLE)?.sessions[caller.agentId]?.effective;
98
+ const captured = effective?.workspace.entries.find(entry => entry.projectId === projectId);
99
+ const branchRef = (ref) => ref.startsWith("refs/heads/") ? ref : `refs/heads/${ref}`;
100
+ if (task?.status !== "active" || !task.projectBindings.some(binding => binding.projectId === projectId)
101
+ || main?.owner.type !== "task" || main.owner.taskId !== taskId
102
+ || effective?.workspace.root !== main.root || entry?.access !== "write"
103
+ || captured?.path !== entry.path || entry.branch === undefined || captured.branch === undefined
104
+ || branchRef(entry.branch) !== branchRef(captured.branch)
105
+ || branchRef(targetRef) !== branchRef(captured.branch)) {
106
+ throw usageError("Managed Leader Integration target must be its captured Task-main branch and checkout.");
107
+ }
108
+ return entry.path;
109
+ }
55
110
  /**
56
111
  * Authority for a live steer/interrupt of an exact current native Turn
57
112
  * (decision-3 §1/§9, message-5 gap B). The legal evidence is the native
@@ -86,9 +141,7 @@ export function projectActor(environment) {
86
141
  return "operator";
87
142
  throw usageError("A managed global Session may manage Project Knowledge only as Operator.");
88
143
  }
89
- if (env.YUI_ROLE !== undefined
90
- || env.YUI_AGENT_ID !== undefined
91
- || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
144
+ if (hasManagedIdentity(env)) {
92
145
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
93
146
  }
94
147
  return "user";
@@ -124,9 +177,7 @@ export function resolveJobCaller(environment, taskId) {
124
177
  nativeSessionId: env.CODEX_THREAD_ID ?? env.YUI_NATIVE_SESSION_ID
125
178
  };
126
179
  }
127
- if (env.YUI_ROLE !== undefined
128
- || env.YUI_AGENT_ID !== undefined
129
- || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
180
+ if (hasManagedIdentity(env)) {
130
181
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
131
182
  }
132
183
  return { scope: "user" };
@@ -1,43 +1,59 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { createRequire } from "node:module";
3
+ import { API_SCRIPT } from "./client/api.js";
3
4
  import { APP_SCRIPT } from "./client/app.js";
4
5
  import { COMPONENTS_SCRIPT } from "./client/components.js";
6
+ import { DETAIL_SCRIPT } from "./client/detail.js";
7
+ import { DOCK_SCRIPT } from "./client/dock.js";
5
8
  import { DOM_SCRIPT } from "./client/dom.js";
9
+ import { EVIDENCE_SCRIPT } from "./client/evidence.js";
6
10
  import { FORMAT_SCRIPT } from "./client/format.js";
11
+ import { FORMS_SCRIPT } from "./client/forms.js";
7
12
  import { I18N_SCRIPT } from "./client/i18n.js";
8
13
  import { MARKDOWN_SCRIPT } from "./client/markdown.js";
14
+ import { OVERVIEW_SCRIPT } from "./client/overview.js";
15
+ import { RECORDS_SCRIPT } from "./client/records.js";
16
+ import { SECTIONS_SCRIPT } from "./client/sections.js";
17
+ import { SIDEBAR_SCRIPT } from "./client/sidebar.js";
9
18
  import { THEME_SCRIPT } from "./client/theme.js";
10
- import { VIEW_SCRIPT } from "./client/view.js";
11
- import { TASK_SURFACE_SCRIPT } from "./client/taskSurface.js";
12
- import { TASK_SUMMARY_SCRIPT } from "./client/taskSummary.js";
13
19
  import { DASHBOARD_HTML } from "./shell.js";
14
20
  import { FONT_FACE_STYLES } from "./fonts.js";
15
21
  import { FONT_WOFF2_BASE64 } from "./fontData.js";
16
- import { CARD_STYLES } from "./styles/cards.js";
22
+ import { BASE_STYLES } from "./styles/base.js";
23
+ import { COMPONENT_STYLES } from "./styles/components.js";
17
24
  import { LAYOUT_STYLES } from "./styles/layout.js";
18
25
  import { MARKDOWN_STYLES } from "./styles/markdown.js";
19
26
  import { RESPONSIVE_STYLES } from "./styles/responsive.js";
20
27
  import { TOKEN_STYLES } from "./styles/tokens.js";
21
- import { WIDGET_STYLES } from "./styles/widgets.js";
28
+ import { VIEW_STYLES } from "./styles/views.js";
22
29
  const require = createRequire(import.meta.url);
30
+ const CSS = "text/css; charset=utf-8";
31
+ const JS = "text/javascript; charset=utf-8";
23
32
  export const WEB_ASSETS = Object.freeze({
24
- "/assets/css/tokens.css": { contentType: "text/css; charset=utf-8", body: TOKEN_STYLES },
25
- "/assets/css/fonts.css": { contentType: "text/css; charset=utf-8", body: FONT_FACE_STYLES },
26
- "/assets/css/layout.css": { contentType: "text/css; charset=utf-8", body: LAYOUT_STYLES },
27
- "/assets/css/widgets.css": { contentType: "text/css; charset=utf-8", body: WIDGET_STYLES },
28
- "/assets/css/cards.css": { contentType: "text/css; charset=utf-8", body: CARD_STYLES },
29
- "/assets/css/markdown.css": { contentType: "text/css; charset=utf-8", body: MARKDOWN_STYLES },
30
- "/assets/css/responsive.css": { contentType: "text/css; charset=utf-8", body: RESPONSIVE_STYLES },
31
- "/assets/js/dom.js": { contentType: "text/javascript; charset=utf-8", body: DOM_SCRIPT },
32
- "/assets/js/format.js": { contentType: "text/javascript; charset=utf-8", body: FORMAT_SCRIPT },
33
- "/assets/js/i18n.js": { contentType: "text/javascript; charset=utf-8", body: I18N_SCRIPT },
34
- "/assets/js/markdown.js": { contentType: "text/javascript; charset=utf-8", body: MARKDOWN_SCRIPT },
35
- "/assets/js/theme.js": { contentType: "text/javascript; charset=utf-8", body: THEME_SCRIPT },
36
- "/assets/js/components.js": { contentType: "text/javascript; charset=utf-8", body: COMPONENTS_SCRIPT },
37
- "/assets/js/view.js": { contentType: "text/javascript; charset=utf-8", body: VIEW_SCRIPT },
38
- "/assets/js/task-surface.js": { contentType: "text/javascript; charset=utf-8", body: TASK_SURFACE_SCRIPT },
39
- "/assets/js/task-summary.js": { contentType: "text/javascript; charset=utf-8", body: TASK_SUMMARY_SCRIPT },
40
- "/assets/app.js": { contentType: "text/javascript; charset=utf-8", body: APP_SCRIPT },
33
+ "/assets/css/fonts.css": { contentType: CSS, body: FONT_FACE_STYLES },
34
+ "/assets/css/tokens.css": { contentType: CSS, body: TOKEN_STYLES },
35
+ "/assets/css/base.css": { contentType: CSS, body: BASE_STYLES },
36
+ "/assets/css/layout.css": { contentType: CSS, body: LAYOUT_STYLES },
37
+ "/assets/css/components.css": { contentType: CSS, body: COMPONENT_STYLES },
38
+ "/assets/css/views.css": { contentType: CSS, body: VIEW_STYLES },
39
+ "/assets/css/markdown.css": { contentType: CSS, body: MARKDOWN_STYLES },
40
+ "/assets/css/responsive.css": { contentType: CSS, body: RESPONSIVE_STYLES },
41
+ "/assets/js/dom.js": { contentType: JS, body: DOM_SCRIPT },
42
+ "/assets/js/format.js": { contentType: JS, body: FORMAT_SCRIPT },
43
+ "/assets/js/i18n.js": { contentType: JS, body: I18N_SCRIPT },
44
+ "/assets/js/markdown.js": { contentType: JS, body: MARKDOWN_SCRIPT },
45
+ "/assets/js/theme.js": { contentType: JS, body: THEME_SCRIPT },
46
+ "/assets/js/api.js": { contentType: JS, body: API_SCRIPT },
47
+ "/assets/js/components.js": { contentType: JS, body: COMPONENTS_SCRIPT },
48
+ "/assets/js/records.js": { contentType: JS, body: RECORDS_SCRIPT },
49
+ "/assets/js/forms.js": { contentType: JS, body: FORMS_SCRIPT },
50
+ "/assets/js/evidence.js": { contentType: JS, body: EVIDENCE_SCRIPT },
51
+ "/assets/js/sidebar.js": { contentType: JS, body: SIDEBAR_SCRIPT },
52
+ "/assets/js/overview.js": { contentType: JS, body: OVERVIEW_SCRIPT },
53
+ "/assets/js/sections.js": { contentType: JS, body: SECTIONS_SCRIPT },
54
+ "/assets/js/detail.js": { contentType: JS, body: DETAIL_SCRIPT },
55
+ "/assets/js/dock.js": { contentType: JS, body: DOCK_SCRIPT },
56
+ "/assets/app.js": { contentType: JS, body: APP_SCRIPT },
41
57
  ...fontAssets(),
42
58
  "/assets/vendor/xterm.mjs": vendorAsset("@xterm/xterm/lib/xterm.mjs", "text/javascript; charset=utf-8"),
43
59
  "/assets/vendor/addon-fit.mjs": vendorAsset("@xterm/addon-fit/lib/addon-fit.mjs", "text/javascript; charset=utf-8"),
@@ -0,0 +1,115 @@
1
+ export const API_SCRIPT = String.raw `
2
+ // Loopback API client. Every request carries the page token; a write is keyed
3
+ // so an unresolved submission can never be silently replayed from this page.
4
+ const token = document.querySelector('meta[name="yui-web-token"]').content;
5
+ const unresolved = new Set();
6
+
7
+ export function pageToken() { return token; }
8
+
9
+ export async function requestJson(path, options) {
10
+ const response = await fetch(path, {
11
+ ...options,
12
+ headers: {
13
+ accept: "application/json",
14
+ "x-yui-web-token": token,
15
+ ...(options && options.headers ? options.headers : {})
16
+ }
17
+ });
18
+ if (!response.ok) {
19
+ let message = "HTTP " + response.status;
20
+ let disposition = "unknown";
21
+ try {
22
+ const body = await response.json();
23
+ if (body && body.error) message = body.error;
24
+ if (body && body.disposition === "not-submitted") disposition = "not-submitted";
25
+ } catch {}
26
+ throw Object.assign(new Error(message), { disposition, status: response.status });
27
+ }
28
+ return response.json();
29
+ }
30
+
31
+ function postJson(path, body, signal) {
32
+ return requestJson(path, {
33
+ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body),
34
+ ...(signal ? { signal } : {})
35
+ });
36
+ }
37
+
38
+ // A key stays blocked until the server either answers or proves the request
39
+ // was not submitted; an unknown outcome must be inspected, not resent.
40
+ export async function submitMutation(key, path, body) {
41
+ if (unresolved.has(key)) {
42
+ throw Object.assign(new Error("An earlier submission is unresolved; read current facts first."), { disposition: "blocked" });
43
+ }
44
+ unresolved.add(key);
45
+ try {
46
+ const receipt = await postJson(path, body);
47
+ unresolved.delete(key);
48
+ return receipt;
49
+ } catch (error) {
50
+ if (error.disposition === "not-submitted") unresolved.delete(key);
51
+ throw error;
52
+ }
53
+ }
54
+
55
+ export function releaseMutation(key) { unresolved.delete(key); }
56
+
57
+ const task = function (taskId) { return "/api/tasks/" + encodeURIComponent(taskId); };
58
+
59
+ export const api = {
60
+ dashboard: function (query) { return requestJson("/api/dashboard?" + query); },
61
+ pageSessions: function (query) {
62
+ return requestJson("/api/dashboard/sessions?" + query, { signal: AbortSignal.timeout(5000) });
63
+ },
64
+ context: function (taskId) { return requestJson(task(taskId) + "/context"); },
65
+ observation: function (taskId) { return requestJson(task(taskId), { signal: AbortSignal.timeout(1500) }); },
66
+ inspect: async function (taskId, ref) {
67
+ const query = new URLSearchParams({ store: ref.store, ref: ref.refId });
68
+ if (ref.digest) query.set("digest", ref.digest);
69
+ let result = await requestJson(task(taskId) + "/inspect?" + query);
70
+ if (!result.contentPage) return result;
71
+ const source = result.contentPage.source;
72
+ const digest = result.contentPage.digest;
73
+ let text = "";
74
+ while (true) {
75
+ const page = result.contentPage;
76
+ if (!page || page.source !== source || page.digest !== digest || page.encoding !== "json"
77
+ || page.offset !== text.length || typeof page.text !== "string" || !page.text.length) {
78
+ throw new Error("Original read changed or returned an invalid page; refresh its Context reference.");
79
+ }
80
+ text += page.text;
81
+ if (page.complete) return JSON.parse(text);
82
+ if (!page.nextCursor) throw new Error("Original read is incomplete; refresh its Context reference.");
83
+ query.set("cursor", page.nextCursor);
84
+ result = await requestJson(task(taskId) + "/inspect?" + query);
85
+ }
86
+ },
87
+ artifacts: function (taskId) { return requestJson(task(taskId) + "/artifacts"); },
88
+ artifact: function (taskId, path, commit) {
89
+ return requestJson(task(taskId) + "/artifacts?" + new URLSearchParams({ path, commit }));
90
+ },
91
+ evidence: function (taskId) { return requestJson(task(taskId) + "/evidence"); },
92
+ panels: function (taskId) { return requestJson(task(taskId) + "/panels", { signal: AbortSignal.timeout(3000) }); },
93
+ readPanel: function (taskId, ref, input) {
94
+ return postJson(task(taskId) + "/panels", { ref, input }, AbortSignal.timeout(3000));
95
+ },
96
+ sendMessage: function (taskId, body, requestId, intent) {
97
+ return submitMutation(taskId + "/messages", task(taskId) + "/messages",
98
+ { body, requestId, ...(intent === undefined ? {} : { intent }) });
99
+ },
100
+ control: function (taskId, payload) {
101
+ return submitMutation(taskId + "/control/" + payload.requestId, task(taskId) + "/control", payload);
102
+ },
103
+ updateTask: function (taskId, patch, requestId) {
104
+ return submitMutation(taskId + "/metadata", task(taskId) + "/metadata", { patch, requestId });
105
+ },
106
+ answerInput: function (taskId, inputId, answer) {
107
+ return submitMutation(taskId + "/input/" + inputId,
108
+ task(taskId) + "/inputs/" + encodeURIComponent(inputId) + "/answer", answer);
109
+ },
110
+ globalState: function (role) { return requestJson("/api/roles/" + encodeURIComponent(role) + "/control"); },
111
+ globalControl: function (role, input) {
112
+ return submitMutation("global/" + role, "/api/roles/" + encodeURIComponent(role) + "/control", input);
113
+ }
114
+ };
115
+ `;