@superatomai/sdk-node 0.0.68-dsp → 0.0.69-dsp
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 +942 -942
- package/dist/index.d.mts +400 -5
- package/dist/index.d.ts +400 -5
- package/dist/index.js +809 -57
- package/dist/index.mjs +824 -78
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -52,11 +52,13 @@ __export(index_exports, {
|
|
|
52
52
|
UIBlock: () => UIBlock,
|
|
53
53
|
UILogCollector: () => UILogCollector,
|
|
54
54
|
UserManager: () => UserManager,
|
|
55
|
+
analyticsClient: () => analyticsClient,
|
|
55
56
|
answerCatalogForBinding: () => answerCatalogForBinding,
|
|
56
57
|
answerComponents: () => answerComponents,
|
|
57
58
|
anthropicLLM: () => anthropicLLM,
|
|
58
59
|
assertReadOnlySql: () => assertReadOnlySql,
|
|
59
60
|
bindContext: () => bindContext,
|
|
61
|
+
bridgePreamble: () => bridgePreamble,
|
|
60
62
|
captureContext: () => captureContext,
|
|
61
63
|
clearContextTokens: () => clearContextTokens,
|
|
62
64
|
contextTokenCount: () => contextTokenCount,
|
|
@@ -72,6 +74,7 @@ __export(index_exports, {
|
|
|
72
74
|
geminiLLM: () => geminiLLM,
|
|
73
75
|
getCodingAgent: () => getCodingAgent,
|
|
74
76
|
getCodingAgentsConfig: () => getCodingAgentsConfig,
|
|
77
|
+
getPiSessionState: () => getPiSessionState,
|
|
75
78
|
getRequestContext: () => getRequestContext,
|
|
76
79
|
groqLLM: () => groqLLM,
|
|
77
80
|
hybridRerank: () => hybridRerank,
|
|
@@ -84,9 +87,11 @@ __export(index_exports, {
|
|
|
84
87
|
mintContextToken: () => mintContextToken,
|
|
85
88
|
normalizeScriptBody: () => normalizeScriptBody,
|
|
86
89
|
onAgentRun: () => onAgentRun,
|
|
90
|
+
onPiSessionUpdate: () => onPiSessionUpdate,
|
|
87
91
|
openaiLLM: () => openaiLLM,
|
|
88
92
|
policiesFromConfig: () => policiesFromConfig,
|
|
89
93
|
projectForDatasetBinding: () => projectForDatasetBinding,
|
|
94
|
+
promptLoader: () => promptLoader,
|
|
90
95
|
queryCache: () => queryCache,
|
|
91
96
|
registerCodingAgentCollection: () => registerCodingAgentCollection,
|
|
92
97
|
registerCodingAgents: () => registerCodingAgents,
|
|
@@ -108,7 +113,8 @@ __export(index_exports, {
|
|
|
108
113
|
userPromptErrorLogger: () => userPromptErrorLogger,
|
|
109
114
|
validateComponentSpec: () => validateComponentSpec,
|
|
110
115
|
withCapturedContext: () => withCapturedContext,
|
|
111
|
-
writeBridgeShims: () => writeBridgeShims
|
|
116
|
+
writeBridgeShims: () => writeBridgeShims,
|
|
117
|
+
writeShims: () => writeShims
|
|
112
118
|
});
|
|
113
119
|
module.exports = __toCommonJS(index_exports);
|
|
114
120
|
|
|
@@ -911,6 +917,101 @@ var CodingAgentAbortRequestMessageSchema = import_zod3.z.object({
|
|
|
911
917
|
type: import_zod3.z.literal("CODING_AGENT_ABORT_REQ"),
|
|
912
918
|
payload: CodingAgentAbortRequestPayloadSchema
|
|
913
919
|
});
|
|
920
|
+
var DashBuilderRequestPayloadSchema = import_zod3.z.object({
|
|
921
|
+
/** The conversation. One per dashboard program, and the abort key. */
|
|
922
|
+
dashboardId: import_zod3.z.string(),
|
|
923
|
+
/** What the person said. */
|
|
924
|
+
text: import_zod3.z.string(),
|
|
925
|
+
/**
|
|
926
|
+
* A panel the person pointed at before typing.
|
|
927
|
+
*
|
|
928
|
+
* Its `Panel` id, the same key a saved arrangement stores against. Optional
|
|
929
|
+
* because most turns are about the dashboard rather than one panel of it, and
|
|
930
|
+
* carried as a field rather than folded into `text` so the transcript shows
|
|
931
|
+
* what the person actually wrote.
|
|
932
|
+
*/
|
|
933
|
+
panelId: import_zod3.z.string().optional(),
|
|
934
|
+
projectId: import_zod3.z.string().optional(),
|
|
935
|
+
userId: import_zod3.z.string().optional()
|
|
936
|
+
});
|
|
937
|
+
var DashBuilderRequestMessageSchema = import_zod3.z.object({
|
|
938
|
+
id: import_zod3.z.string(),
|
|
939
|
+
from: MessageParticipantSchema,
|
|
940
|
+
type: import_zod3.z.literal("DASH_BUILDER_REQ"),
|
|
941
|
+
payload: DashBuilderRequestPayloadSchema
|
|
942
|
+
});
|
|
943
|
+
var DashBuilderUpdateSchema = import_zod3.z.discriminatedUnion("type", [
|
|
944
|
+
import_zod3.z.object({ type: import_zod3.z.literal("state"), running: import_zod3.z.boolean() }),
|
|
945
|
+
import_zod3.z.object({ type: import_zod3.z.literal("user"), text: import_zod3.z.string(), at: import_zod3.z.number() }),
|
|
946
|
+
/**
|
|
947
|
+
* The tail of an assistant message that is still being written.
|
|
948
|
+
*
|
|
949
|
+
* Append-only and never part of the transcript: the `assistant` update that
|
|
950
|
+
* follows carries the same prose in full, so a client shows the accumulated
|
|
951
|
+
* deltas while a turn runs and drops them the moment the real message lands.
|
|
952
|
+
* A turn here runs for minutes, and without this the pane sits empty for all
|
|
953
|
+
* of it.
|
|
954
|
+
*/
|
|
955
|
+
import_zod3.z.object({ type: import_zod3.z.literal("delta"), text: import_zod3.z.string() }),
|
|
956
|
+
import_zod3.z.object({ type: import_zod3.z.literal("assistant"), text: import_zod3.z.string(), at: import_zod3.z.number() }),
|
|
957
|
+
import_zod3.z.object({ type: import_zod3.z.literal("tool"), text: import_zod3.z.string(), at: import_zod3.z.number() }),
|
|
958
|
+
import_zod3.z.object({ type: import_zod3.z.literal("error"), text: import_zod3.z.string(), at: import_zod3.z.number() })
|
|
959
|
+
]);
|
|
960
|
+
var DashBuilderStreamPayloadSchema = import_zod3.z.object({
|
|
961
|
+
dashboardId: import_zod3.z.string(),
|
|
962
|
+
/**
|
|
963
|
+
* Monotonic per turn, so re-delivery is harmless.
|
|
964
|
+
*
|
|
965
|
+
* Copied from dashboard-agent rather than assumed unnecessary: duplicate and
|
|
966
|
+
* out-of-order delivery were observed there on long-running requests and were
|
|
967
|
+
* never explained by anything in the send/receive path itself. A turn here
|
|
968
|
+
* runs for minutes, which is the same exposure.
|
|
969
|
+
*/
|
|
970
|
+
seq: import_zod3.z.number(),
|
|
971
|
+
update: DashBuilderUpdateSchema
|
|
972
|
+
});
|
|
973
|
+
var DashBuilderStreamMessageSchema = import_zod3.z.object({
|
|
974
|
+
id: import_zod3.z.string().optional(),
|
|
975
|
+
from: MessageParticipantSchema,
|
|
976
|
+
type: import_zod3.z.literal("DASH_BUILDER_STREAM"),
|
|
977
|
+
payload: DashBuilderStreamPayloadSchema
|
|
978
|
+
});
|
|
979
|
+
var DashBuilderAbortRequestPayloadSchema = import_zod3.z.object({
|
|
980
|
+
dashboardId: import_zod3.z.string()
|
|
981
|
+
});
|
|
982
|
+
var DashBuilderAbortRequestMessageSchema = import_zod3.z.object({
|
|
983
|
+
id: import_zod3.z.string().optional(),
|
|
984
|
+
from: MessageParticipantSchema,
|
|
985
|
+
type: import_zod3.z.literal("DASH_BUILDER_ABORT_REQ"),
|
|
986
|
+
payload: DashBuilderAbortRequestPayloadSchema
|
|
987
|
+
});
|
|
988
|
+
var DashComponentPropSchema = import_zod3.z.union([
|
|
989
|
+
import_zod3.z.string(),
|
|
990
|
+
import_zod3.z.object({
|
|
991
|
+
description: import_zod3.z.string(),
|
|
992
|
+
importance: import_zod3.z.enum(["required", "recommended", "optional"]).optional(),
|
|
993
|
+
default: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean()]).optional(),
|
|
994
|
+
caution: import_zod3.z.string().optional(),
|
|
995
|
+
group: import_zod3.z.string().optional()
|
|
996
|
+
})
|
|
997
|
+
]);
|
|
998
|
+
var DashComponentSchema = import_zod3.z.object({
|
|
999
|
+
name: import_zod3.z.string(),
|
|
1000
|
+
kind: import_zod3.z.string(),
|
|
1001
|
+
purpose: import_zod3.z.string(),
|
|
1002
|
+
props: import_zod3.z.record(DashComponentPropSchema).optional(),
|
|
1003
|
+
useWhen: import_zod3.z.string().optional(),
|
|
1004
|
+
notes: import_zod3.z.string().optional()
|
|
1005
|
+
});
|
|
1006
|
+
var DashContractResponsePayloadSchema = import_zod3.z.object({
|
|
1007
|
+
components: import_zod3.z.array(DashComponentSchema)
|
|
1008
|
+
});
|
|
1009
|
+
var DashContractResponseMessageSchema = import_zod3.z.object({
|
|
1010
|
+
id: import_zod3.z.string(),
|
|
1011
|
+
from: MessageParticipantSchema,
|
|
1012
|
+
type: import_zod3.z.literal("DASH_CONTRACT_RES"),
|
|
1013
|
+
payload: DashContractResponsePayloadSchema
|
|
1014
|
+
});
|
|
914
1015
|
var ReportCompRequestPayloadSchema = import_zod3.z.object({
|
|
915
1016
|
prompt: import_zod3.z.string(),
|
|
916
1017
|
userId: import_zod3.z.string().optional(),
|
|
@@ -3835,7 +3936,7 @@ var TaggedStreamBuffer = class extends StreamBuffer {
|
|
|
3835
3936
|
}
|
|
3836
3937
|
};
|
|
3837
3938
|
function streamDelay(ms = STREAM_DELAY_MS) {
|
|
3838
|
-
return new Promise((
|
|
3939
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
3839
3940
|
}
|
|
3840
3941
|
async function withProgressHeartbeat(operation, progressMessage, streamBuffer, intervalMs = PROGRESS_HEARTBEAT_INTERVAL_MS) {
|
|
3841
3942
|
if (!streamBuffer.hasCallback()) {
|
|
@@ -11016,7 +11117,7 @@ var Semaphore = class {
|
|
|
11016
11117
|
`Script execution at capacity (${this.max} running, ${this.waiters.length} queued). Try again shortly.`
|
|
11017
11118
|
);
|
|
11018
11119
|
}
|
|
11019
|
-
return new Promise((
|
|
11120
|
+
return new Promise((resolve3) => this.waiters.push(resolve3));
|
|
11020
11121
|
}
|
|
11021
11122
|
release() {
|
|
11022
11123
|
const next = this.waiters.shift();
|
|
@@ -11146,7 +11247,7 @@ FIX: pass every required parameter to execute_script, or give it a default in wr
|
|
|
11146
11247
|
}
|
|
11147
11248
|
}
|
|
11148
11249
|
function executeInSubprocess(scriptPath, params, paramSchema, externalTools, streamBuffer, timeoutMs, signal, mode, analysisData, analysisDatasets, entities, appliedPolicies) {
|
|
11149
|
-
return new Promise((
|
|
11250
|
+
return new Promise((resolve3) => {
|
|
11150
11251
|
const tsxBin = resolveTsxBinary();
|
|
11151
11252
|
const bootstrap = resolveBootstrapPath();
|
|
11152
11253
|
const contextToken = mintContextToken();
|
|
@@ -11202,7 +11303,7 @@ function executeInSubprocess(scriptPath, params, paramSchema, externalTools, str
|
|
|
11202
11303
|
clearTimeout(timer);
|
|
11203
11304
|
if (signal && onAbort) signal.removeEventListener("abort", onAbort);
|
|
11204
11305
|
cleanup();
|
|
11205
|
-
|
|
11306
|
+
resolve3(r);
|
|
11206
11307
|
};
|
|
11207
11308
|
const timer = setTimeout(() => {
|
|
11208
11309
|
finish({
|
|
@@ -18901,7 +19002,25 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
|
|
|
18901
19002
|
}
|
|
18902
19003
|
}
|
|
18903
19004
|
if (!usedLightweight) {
|
|
18904
|
-
logger.warn(`[AgentFlow] Component generation produced
|
|
19005
|
+
logger.warn(`[AgentFlow] Component generation produced no components \u2014 returning the analysis without a dashboard`);
|
|
19006
|
+
}
|
|
19007
|
+
}
|
|
19008
|
+
if (matchedComponents.length === 0) {
|
|
19009
|
+
const fallbackText = (agentResponse.text || "").replace(/<DashboardComponents>[\s\S]*?<\/DashboardComponents>/g, "").trim();
|
|
19010
|
+
if (fallbackText) {
|
|
19011
|
+
logger.info(`[AgentFlow] No components \u2014 wrapping the analysis in DynamicMarkdownBlock`);
|
|
19012
|
+
matchedComponents = [{
|
|
19013
|
+
id: "dynamic-markdown-block",
|
|
19014
|
+
name: "DynamicMarkdownBlock",
|
|
19015
|
+
type: "MarkdownBlock",
|
|
19016
|
+
description: "Text response rendered as markdown",
|
|
19017
|
+
props: { content: fallbackText }
|
|
19018
|
+
}];
|
|
19019
|
+
layoutTitle = "";
|
|
19020
|
+
layoutDescription = "";
|
|
19021
|
+
noDataAnswer = true;
|
|
19022
|
+
} else {
|
|
19023
|
+
logger.warn(`[AgentFlow] No components and no analysis text \u2014 returning an empty result`);
|
|
18905
19024
|
}
|
|
18906
19025
|
}
|
|
18907
19026
|
const queryMap = {};
|
|
@@ -19842,12 +19961,13 @@ async function handleUserPromptRequest(data, components, sendMessage, anthropicA
|
|
|
19842
19961
|
id: `comp_${Math.random().toString(36).substring(2, 8)}`
|
|
19843
19962
|
}));
|
|
19844
19963
|
}
|
|
19964
|
+
const { trace: _trace, ...dataWithoutTrace } = response.data ?? {};
|
|
19845
19965
|
sendDataResponse4(
|
|
19846
19966
|
response.id || data.id,
|
|
19847
19967
|
{
|
|
19848
19968
|
success: response.success,
|
|
19849
19969
|
errors: response.errors,
|
|
19850
|
-
data: response.data,
|
|
19970
|
+
data: response.data ? dataWithoutTrace : response.data,
|
|
19851
19971
|
uiBlockId: response.uiBlockId,
|
|
19852
19972
|
threadId: response.threadId
|
|
19853
19973
|
},
|
|
@@ -20044,6 +20164,26 @@ async function handleComponentListResponse(data, storeComponents, collections) {
|
|
|
20044
20164
|
}
|
|
20045
20165
|
}
|
|
20046
20166
|
|
|
20167
|
+
// src/handlers/dash-contract-response.ts
|
|
20168
|
+
async function handleDashContractResponse(data, storeDashContract, collections) {
|
|
20169
|
+
const parsed = DashContractResponseMessageSchema.safeParse(data);
|
|
20170
|
+
if (!parsed.success) {
|
|
20171
|
+
logger.error("[DashContract] Invalid message \u2014 ignoring");
|
|
20172
|
+
return;
|
|
20173
|
+
}
|
|
20174
|
+
const { components } = parsed.data.payload;
|
|
20175
|
+
storeDashContract(components);
|
|
20176
|
+
const register = collections?.["dashboard-builder"]?.["registerContract"];
|
|
20177
|
+
if (!register) return;
|
|
20178
|
+
try {
|
|
20179
|
+
await register({ components });
|
|
20180
|
+
} catch (error) {
|
|
20181
|
+
logger.warn(
|
|
20182
|
+
`[DashContract] Collection refused the contract: ${error instanceof Error ? error.message : String(error)}`
|
|
20183
|
+
);
|
|
20184
|
+
}
|
|
20185
|
+
}
|
|
20186
|
+
|
|
20047
20187
|
// src/handlers/workflow-list-response.ts
|
|
20048
20188
|
async function handleWorkflowListResponse(data, storeWorkflows) {
|
|
20049
20189
|
try {
|
|
@@ -24441,11 +24581,257 @@ ${marker}
|
|
|
24441
24581
|
};
|
|
24442
24582
|
}
|
|
24443
24583
|
|
|
24584
|
+
// src/codingAgent/drivers/pi.ts
|
|
24585
|
+
var dynamicImport2 = new Function("specifier", "return import(specifier)");
|
|
24586
|
+
var piModulePromise = null;
|
|
24587
|
+
function loadPi() {
|
|
24588
|
+
if (!piModulePromise) {
|
|
24589
|
+
piModulePromise = dynamicImport2("@earendil-works/pi-coding-agent").catch((err) => {
|
|
24590
|
+
piModulePromise = null;
|
|
24591
|
+
throw new Error(`@earendil-works/pi-coding-agent is not installed, so the pi harness is unavailable. (${err?.message ?? err})`);
|
|
24592
|
+
});
|
|
24593
|
+
}
|
|
24594
|
+
return piModulePromise;
|
|
24595
|
+
}
|
|
24596
|
+
var authAndRegistry = null;
|
|
24597
|
+
function getAuthAndRegistry() {
|
|
24598
|
+
if (!authAndRegistry) {
|
|
24599
|
+
authAndRegistry = loadPi().then(({ AuthStorage, ModelRegistry }) => {
|
|
24600
|
+
const authStorage = AuthStorage.create();
|
|
24601
|
+
return { authStorage, modelRegistry: ModelRegistry.create(authStorage) };
|
|
24602
|
+
});
|
|
24603
|
+
}
|
|
24604
|
+
return authAndRegistry;
|
|
24605
|
+
}
|
|
24606
|
+
var DEFAULT_PROVIDER = "openai-codex";
|
|
24607
|
+
var DEFAULT_MODEL_ID = process.env.PI_AGENT_MODEL || "gpt-5.5";
|
|
24608
|
+
var KNOWN_UNUSABLE_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.3-codex-spark"]);
|
|
24609
|
+
async function resolveModel(modelRegistry, spec) {
|
|
24610
|
+
const [provider, modelId] = spec?.includes("/") ? [spec.slice(0, spec.indexOf("/")), spec.slice(spec.indexOf("/") + 1)] : [spec || DEFAULT_PROVIDER, void 0];
|
|
24611
|
+
const available = modelRegistry.getAvailable().filter((m) => m.provider === provider);
|
|
24612
|
+
const wanted = modelId ?? (spec ? void 0 : DEFAULT_MODEL_ID);
|
|
24613
|
+
const exact = wanted && (modelRegistry.find(provider, wanted) ?? available.find((m) => m.id === wanted));
|
|
24614
|
+
if (exact && modelRegistry.hasConfiguredAuth(exact)) return exact;
|
|
24615
|
+
const usable = available.filter((m) => !KNOWN_UNUSABLE_MODEL_IDS.has(m.id));
|
|
24616
|
+
if (usable.length) return usable[0];
|
|
24617
|
+
if (available.length) return available[0];
|
|
24618
|
+
throw new Error(
|
|
24619
|
+
`No model available from "${provider}". Authorise it in a terminal on this machine: run \`pi\`, then \`/login\`.`
|
|
24620
|
+
);
|
|
24621
|
+
}
|
|
24622
|
+
function emptyUsage2() {
|
|
24623
|
+
return { inputTokens: 0, outputTokens: 0, reasoningTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, toolCalls: 0 };
|
|
24624
|
+
}
|
|
24625
|
+
var BUFFER_CAP2 = 64e3;
|
|
24626
|
+
var EVENT_CAP2 = 600;
|
|
24627
|
+
function normEvent2(ev) {
|
|
24628
|
+
switch (ev.type) {
|
|
24629
|
+
case "tool_execution_start":
|
|
24630
|
+
return { kind: "command", id: ev.toolCallId, command: ev.toolName ? `${ev.toolName} ${jsonPreview(ev.args)}` : void 0, status: "in_progress" };
|
|
24631
|
+
case "tool_execution_end":
|
|
24632
|
+
return { kind: "command", id: ev.toolCallId, status: ev.isError ? "failed" : "completed", done: true, output: textOf(ev.result) };
|
|
24633
|
+
default:
|
|
24634
|
+
return null;
|
|
24635
|
+
}
|
|
24636
|
+
}
|
|
24637
|
+
function jsonPreview(v) {
|
|
24638
|
+
if (v == null) return "";
|
|
24639
|
+
try {
|
|
24640
|
+
return JSON.stringify(v).slice(0, 160);
|
|
24641
|
+
} catch {
|
|
24642
|
+
return "";
|
|
24643
|
+
}
|
|
24644
|
+
}
|
|
24645
|
+
function textOf(content) {
|
|
24646
|
+
const blocks = content?.content ?? content;
|
|
24647
|
+
if (!Array.isArray(blocks)) return typeof content === "string" ? content : "";
|
|
24648
|
+
return blocks.filter((b) => b?.type === "text").map((b) => String(b.text ?? "")).join("").trim();
|
|
24649
|
+
}
|
|
24650
|
+
var TRANSCRIPT_CAP = 400;
|
|
24651
|
+
var sessionListeners = /* @__PURE__ */ new Set();
|
|
24652
|
+
function onPiSessionUpdate(listener) {
|
|
24653
|
+
sessionListeners.add(listener);
|
|
24654
|
+
return () => sessionListeners.delete(listener);
|
|
24655
|
+
}
|
|
24656
|
+
function getPiSessionState(sessionKey) {
|
|
24657
|
+
const live = liveSessions.get(sessionKey);
|
|
24658
|
+
return live ? { running: live.running, transcript: live.transcript } : void 0;
|
|
24659
|
+
}
|
|
24660
|
+
function publish(sessionKey, live, entry) {
|
|
24661
|
+
live.transcript.push(entry);
|
|
24662
|
+
if (live.transcript.length > TRANSCRIPT_CAP) live.transcript.splice(0, live.transcript.length - TRANSCRIPT_CAP);
|
|
24663
|
+
for (const listener of sessionListeners) listener(sessionKey, entry);
|
|
24664
|
+
}
|
|
24665
|
+
var liveSessions = /* @__PURE__ */ new Map();
|
|
24666
|
+
function newSessionId() {
|
|
24667
|
+
return `pi_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
24668
|
+
}
|
|
24669
|
+
var IDLE_TIMEOUT_MS = Number(process.env.PI_AGENT_IDLE_MS ?? 30 * 60 * 1e3);
|
|
24670
|
+
var sweeper = null;
|
|
24671
|
+
function startSweeper() {
|
|
24672
|
+
if (sweeper) return;
|
|
24673
|
+
sweeper = setInterval(() => {
|
|
24674
|
+
const cutoff = Date.now() - IDLE_TIMEOUT_MS;
|
|
24675
|
+
for (const [key, live] of liveSessions) {
|
|
24676
|
+
if (live.running || live.lastActive > cutoff) continue;
|
|
24677
|
+
live.session.dispose();
|
|
24678
|
+
liveSessions.delete(key);
|
|
24679
|
+
}
|
|
24680
|
+
if (liveSessions.size === 0 && sweeper) {
|
|
24681
|
+
clearInterval(sweeper);
|
|
24682
|
+
sweeper = null;
|
|
24683
|
+
}
|
|
24684
|
+
}, 6e4);
|
|
24685
|
+
sweeper.unref?.();
|
|
24686
|
+
}
|
|
24687
|
+
function createPiSession(opts) {
|
|
24688
|
+
let running = false;
|
|
24689
|
+
let sessionKey = opts.resumeId && liveSessions.has(opts.resumeId) ? opts.resumeId : void 0;
|
|
24690
|
+
async function ensureSession() {
|
|
24691
|
+
const existing = sessionKey ? liveSessions.get(sessionKey) : void 0;
|
|
24692
|
+
if (existing) return existing;
|
|
24693
|
+
const { createAgentSession, SessionManager } = await loadPi();
|
|
24694
|
+
const { authStorage, modelRegistry } = await getAuthAndRegistry();
|
|
24695
|
+
const model = await resolveModel(modelRegistry, opts.model);
|
|
24696
|
+
const { session } = await createAgentSession({
|
|
24697
|
+
cwd: opts.cwd,
|
|
24698
|
+
sessionManager: SessionManager.inMemory(),
|
|
24699
|
+
authStorage,
|
|
24700
|
+
modelRegistry,
|
|
24701
|
+
model,
|
|
24702
|
+
tools: opts.tools ?? ["bash"]
|
|
24703
|
+
});
|
|
24704
|
+
sessionKey = newSessionId();
|
|
24705
|
+
const live = { session, running: false, transcript: [], lastActive: Date.now(), eventLog: [], buf: "" };
|
|
24706
|
+
liveSessions.set(sessionKey, live);
|
|
24707
|
+
startSweeper();
|
|
24708
|
+
return live;
|
|
24709
|
+
}
|
|
24710
|
+
async function runTurn(prompt, handlers, signal) {
|
|
24711
|
+
const startedAt = Date.now();
|
|
24712
|
+
const usage = emptyUsage2();
|
|
24713
|
+
let status = "completed";
|
|
24714
|
+
let error;
|
|
24715
|
+
const finish = (live2) => ({
|
|
24716
|
+
status,
|
|
24717
|
+
answer: status === "error" || status === "aborted" ? "" : live2?.session.getLastAssistantText()?.trim() ?? "",
|
|
24718
|
+
ms: Date.now() - startedAt,
|
|
24719
|
+
usage,
|
|
24720
|
+
error,
|
|
24721
|
+
sessionId: sessionKey
|
|
24722
|
+
});
|
|
24723
|
+
if (signal?.aborted) {
|
|
24724
|
+
status = "aborted";
|
|
24725
|
+
return finish();
|
|
24726
|
+
}
|
|
24727
|
+
const live = await ensureSession();
|
|
24728
|
+
const key = sessionKey;
|
|
24729
|
+
live.running = true;
|
|
24730
|
+
live.lastActive = Date.now();
|
|
24731
|
+
publish(key, live, { at: Date.now(), kind: "user", text: prompt });
|
|
24732
|
+
const before = live.session.getSessionStats();
|
|
24733
|
+
const onAbort = () => {
|
|
24734
|
+
void live.session.abort();
|
|
24735
|
+
};
|
|
24736
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
24737
|
+
const emit = (chunk) => {
|
|
24738
|
+
live.buf = (live.buf + chunk).slice(-BUFFER_CAP2);
|
|
24739
|
+
handlers?.onOutput?.(chunk);
|
|
24740
|
+
};
|
|
24741
|
+
const unsubscribe = live.session.subscribe((ev) => {
|
|
24742
|
+
if (ev.type === "message_update" && ev.assistantMessageEvent?.type === "text_delta") {
|
|
24743
|
+
const delta = ev.assistantMessageEvent.delta;
|
|
24744
|
+
if (delta) {
|
|
24745
|
+
emit(delta);
|
|
24746
|
+
handlers?.onNarration?.(delta);
|
|
24747
|
+
}
|
|
24748
|
+
return;
|
|
24749
|
+
}
|
|
24750
|
+
if (ev.type === "tool_execution_start" || ev.type === "tool_execution_end") {
|
|
24751
|
+
if (ev.type === "tool_execution_end") usage.toolCalls++;
|
|
24752
|
+
const event = normEvent2(ev);
|
|
24753
|
+
if (!event) return;
|
|
24754
|
+
live.eventLog.push(event);
|
|
24755
|
+
if (live.eventLog.length > EVENT_CAP2) live.eventLog.shift();
|
|
24756
|
+
handlers?.onEvent?.(event);
|
|
24757
|
+
publish(key, live, { at: Date.now(), kind: "activity", event });
|
|
24758
|
+
if (ev.type === "tool_execution_start") emit(`
|
|
24759
|
+
\u2192 ${ev.toolName ?? "tool"} ${jsonPreview(ev.args)}
|
|
24760
|
+
`);
|
|
24761
|
+
return;
|
|
24762
|
+
}
|
|
24763
|
+
});
|
|
24764
|
+
try {
|
|
24765
|
+
if (signal?.aborted) {
|
|
24766
|
+
status = "aborted";
|
|
24767
|
+
return finish(live);
|
|
24768
|
+
}
|
|
24769
|
+
await live.session.prompt(prompt);
|
|
24770
|
+
const err = live.session.agent.state.errorMessage;
|
|
24771
|
+
if (err) {
|
|
24772
|
+
status = signal?.aborted ? "aborted" : "error";
|
|
24773
|
+
error = err;
|
|
24774
|
+
} else if (signal?.aborted) {
|
|
24775
|
+
status = "aborted";
|
|
24776
|
+
}
|
|
24777
|
+
} catch (err) {
|
|
24778
|
+
status = signal?.aborted ? "aborted" : "error";
|
|
24779
|
+
error = err?.message ?? String(err);
|
|
24780
|
+
} finally {
|
|
24781
|
+
unsubscribe();
|
|
24782
|
+
signal?.removeEventListener("abort", onAbort);
|
|
24783
|
+
live.running = false;
|
|
24784
|
+
live.lastActive = Date.now();
|
|
24785
|
+
}
|
|
24786
|
+
const after = live.session.getSessionStats();
|
|
24787
|
+
usage.inputTokens = Math.max(0, after.tokens.input - before.tokens.input);
|
|
24788
|
+
usage.outputTokens = Math.max(0, after.tokens.output - before.tokens.output);
|
|
24789
|
+
usage.cacheReadTokens = Math.max(0, after.tokens.cacheRead - before.tokens.cacheRead);
|
|
24790
|
+
usage.cacheWriteTokens = Math.max(0, after.tokens.cacheWrite - before.tokens.cacheWrite);
|
|
24791
|
+
usage.costUSD = Math.max(0, after.cost - before.cost);
|
|
24792
|
+
handlers?.onUsage?.({ ...usage });
|
|
24793
|
+
const result = finish(live);
|
|
24794
|
+
publish(key, live, result.status === "error" ? { at: Date.now(), kind: "error", text: result.error } : { at: Date.now(), kind: "assistant", text: result.answer });
|
|
24795
|
+
return result;
|
|
24796
|
+
}
|
|
24797
|
+
return {
|
|
24798
|
+
harness: "pi",
|
|
24799
|
+
kind: "events",
|
|
24800
|
+
async run(prompt, handlers, signal) {
|
|
24801
|
+
if (running) throw new Error("This pi session already has a turn in flight.");
|
|
24802
|
+
running = true;
|
|
24803
|
+
try {
|
|
24804
|
+
return await runTurn(prompt, handlers, signal);
|
|
24805
|
+
} finally {
|
|
24806
|
+
running = false;
|
|
24807
|
+
}
|
|
24808
|
+
},
|
|
24809
|
+
events: () => sessionKey ? liveSessions.get(sessionKey)?.eventLog ?? [] : [],
|
|
24810
|
+
buffer: () => sessionKey ? liveSessions.get(sessionKey)?.buf ?? "" : "",
|
|
24811
|
+
busy: () => running,
|
|
24812
|
+
sessionId: () => sessionKey,
|
|
24813
|
+
// Abandon for real — drop the live session so the next run starts fresh.
|
|
24814
|
+
reset: () => {
|
|
24815
|
+
if (sessionKey) {
|
|
24816
|
+
liveSessions.get(sessionKey)?.session.dispose();
|
|
24817
|
+
liveSessions.delete(sessionKey);
|
|
24818
|
+
}
|
|
24819
|
+
sessionKey = void 0;
|
|
24820
|
+
},
|
|
24821
|
+
// Local-only, same as the codex driver: the live session stays in the
|
|
24822
|
+
// module map so a later run with this sessionId can still resume it.
|
|
24823
|
+
dispose: () => {
|
|
24824
|
+
}
|
|
24825
|
+
};
|
|
24826
|
+
}
|
|
24827
|
+
|
|
24444
24828
|
// src/codingAgent/factory.ts
|
|
24445
24829
|
function createCodingAgentSession(harness, opts) {
|
|
24446
24830
|
switch (harness) {
|
|
24447
24831
|
case "codex":
|
|
24448
24832
|
return createCodexSession(opts);
|
|
24833
|
+
case "pi":
|
|
24834
|
+
return createPiSession(opts);
|
|
24449
24835
|
default:
|
|
24450
24836
|
throw new Error(`Unknown coding-agent harness: ${harness}`);
|
|
24451
24837
|
}
|
|
@@ -24847,9 +25233,6 @@ Fix ONLY that, and rewrite the same file at the same path. Do not re-run any que
|
|
|
24847
25233
|
}
|
|
24848
25234
|
}
|
|
24849
25235
|
|
|
24850
|
-
// src/codingAgent/tools/bridge-shims.ts
|
|
24851
|
-
var fs9 = __toESM(require("fs"));
|
|
24852
|
-
|
|
24853
25236
|
// src/codingAgent/tools/read-only-sql.ts
|
|
24854
25237
|
var WRITE_KEYWORDS = [
|
|
24855
25238
|
"insert",
|
|
@@ -24904,9 +25287,45 @@ ${stripSqlNoise.toString()}
|
|
|
24904
25287
|
${assertReadOnlySql.toString().replace("export function", "function")}
|
|
24905
25288
|
`;
|
|
24906
25289
|
|
|
25290
|
+
// src/codingAgent/tools/shims.ts
|
|
25291
|
+
var fs9 = __toESM(require("fs"));
|
|
25292
|
+
var path10 = __toESM(require("path"));
|
|
25293
|
+
var resolve2 = (target, name) => typeof target === "string" ? path10.join(target, name) : target.pathTo(name);
|
|
25294
|
+
function writeShims(defs, target) {
|
|
25295
|
+
for (const def of defs) {
|
|
25296
|
+
const file = resolve2(target, def.name);
|
|
25297
|
+
fs9.writeFileSync(file, def.body, "utf-8");
|
|
25298
|
+
fs9.chmodSync(file, 493);
|
|
25299
|
+
}
|
|
25300
|
+
return defs.map((def) => ({ name: `./${def.name}`, summary: def.summary }));
|
|
25301
|
+
}
|
|
25302
|
+
function bridgePreamble(bridgeUrl, constants = {}) {
|
|
25303
|
+
const declared = Object.entries(constants).map(([name, value]) => `const ${name} = ${JSON.stringify(value)};`).join("\n");
|
|
25304
|
+
return `const BRIDGE = ${JSON.stringify(bridgeUrl)};
|
|
25305
|
+
${declared}
|
|
25306
|
+
|
|
25307
|
+
function post(path, payload) {
|
|
25308
|
+
return fetch(BRIDGE + path, {
|
|
25309
|
+
method: 'POST',
|
|
25310
|
+
headers: { 'content-type': 'application/json' },
|
|
25311
|
+
body: JSON.stringify(payload),
|
|
25312
|
+
}).then(async (r) => {
|
|
25313
|
+
const text = await r.text();
|
|
25314
|
+
if (!r.ok) { console.error('Request failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25315
|
+
try { return JSON.parse(text); } catch { console.error(text); process.exit(1); }
|
|
25316
|
+
}).catch((e) => { console.error('Could not reach the backend: ' + (e && e.message)); process.exit(1); });
|
|
25317
|
+
}
|
|
25318
|
+
`;
|
|
25319
|
+
}
|
|
25320
|
+
|
|
24907
25321
|
// src/codingAgent/tools/bridge-shims.ts
|
|
24908
25322
|
function writeBridgeShims(ws, opts) {
|
|
24909
25323
|
const maxRows = opts.maxRows ?? 200;
|
|
25324
|
+
const directTools = opts.directTools ?? [];
|
|
25325
|
+
const entityTypes = opts.entityTypes ?? [];
|
|
25326
|
+
const conceptCatalog = opts.conceptCatalog ?? [];
|
|
25327
|
+
const hasKnowledgeBase = !!opts.knowledgeBase;
|
|
25328
|
+
const hasSearchableSource = opts.sources.some((s) => s.searchable);
|
|
24910
25329
|
const query = `#!/usr/bin/env node
|
|
24911
25330
|
// Read-only SQL against a data source. Generated per run \u2014 do not edit.
|
|
24912
25331
|
${READ_ONLY_SQL_SOURCE}
|
|
@@ -24916,7 +25335,7 @@ const CONTEXT_TOKEN = ${JSON.stringify(opts.contextToken ?? null)};
|
|
|
24916
25335
|
|
|
24917
25336
|
const [toolId, sql, limitArg] = process.argv.slice(2);
|
|
24918
25337
|
if (!toolId || !sql) {
|
|
24919
|
-
console.error('usage: ./query "<toolId>" "<sql>" [limit]\\nRun ./sources for the toolIds.');
|
|
25338
|
+
console.error('usage: node ./query "<toolId>" "<sql>" [limit]\\nRun: node ./sources \u2014 for the toolIds.');
|
|
24920
25339
|
process.exit(2);
|
|
24921
25340
|
}
|
|
24922
25341
|
try { assertReadOnlySql(sql); } catch (e) { console.error(String(e.message || e)); process.exit(2); }
|
|
@@ -24958,24 +25377,189 @@ fetch(BRIDGE + '/query', {
|
|
|
24958
25377
|
})
|
|
24959
25378
|
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
24960
25379
|
`;
|
|
24961
|
-
const
|
|
24962
|
-
//
|
|
24963
|
-
|
|
25380
|
+
const runTool = `#!/usr/bin/env node
|
|
25381
|
+
// Invoke a pre-built business-logic tool. Generated per run \u2014 do not edit.
|
|
25382
|
+
const BRIDGE = ${JSON.stringify(opts.bridgeUrl)};
|
|
25383
|
+
|
|
25384
|
+
const [toolId, paramsArg] = process.argv.slice(2);
|
|
25385
|
+
if (!toolId) {
|
|
25386
|
+
console.error('usage: node ./run-tool "<toolId>" [\\'<json params>\\']\\nRun: node ./sources \u2014 for the toolIds and their params.');
|
|
25387
|
+
process.exit(2);
|
|
25388
|
+
}
|
|
25389
|
+
let params = {};
|
|
25390
|
+
if (paramsArg) {
|
|
25391
|
+
try { params = JSON.parse(paramsArg); }
|
|
25392
|
+
catch (e) { console.error('params must be JSON: ' + String(e.message || e)); process.exit(2); }
|
|
25393
|
+
}
|
|
25394
|
+
|
|
25395
|
+
fetch(BRIDGE + '/run-tool', {
|
|
25396
|
+
method: 'POST',
|
|
25397
|
+
headers: { 'content-type': 'application/json' },
|
|
25398
|
+
body: JSON.stringify({ toolId, params }),
|
|
25399
|
+
})
|
|
25400
|
+
.then(async (r) => {
|
|
25401
|
+
const text = await r.text();
|
|
25402
|
+
if (!r.ok) { console.error('Tool call failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25403
|
+
let p; try { p = JSON.parse(text); } catch { console.log(text); return; }
|
|
25404
|
+
if (p && p.error) { console.error(String(p.error)); process.exit(1); }
|
|
25405
|
+
console.log(JSON.stringify(p.result ?? p, null, 2));
|
|
25406
|
+
})
|
|
25407
|
+
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
25408
|
+
`;
|
|
25409
|
+
const schemaSearch = `#!/usr/bin/env node
|
|
25410
|
+
// Keyword search over a large source's schema \u2014 call this BEFORE writing SQL
|
|
25411
|
+
// against a "searchable" source (see ./sources); its schema is too big to
|
|
25412
|
+
// have been shown to you in full, and guessing column names wastes a turn on
|
|
25413
|
+
// a failed query. Generated per run \u2014 do not edit.
|
|
25414
|
+
const BRIDGE = ${JSON.stringify(opts.bridgeUrl)};
|
|
25415
|
+
|
|
25416
|
+
const [toolId, ...keywords] = process.argv.slice(2);
|
|
25417
|
+
if (!toolId || !keywords.length) {
|
|
25418
|
+
console.error('usage: node ./schema-search "<toolId>" <keyword> [keyword...]\\nRun: node ./sources \u2014 for which toolIds are searchable.');
|
|
25419
|
+
process.exit(2);
|
|
25420
|
+
}
|
|
25421
|
+
|
|
25422
|
+
fetch(BRIDGE + '/schema-search', {
|
|
25423
|
+
method: 'POST',
|
|
25424
|
+
headers: { 'content-type': 'application/json' },
|
|
25425
|
+
body: JSON.stringify({ toolId, keywords }),
|
|
25426
|
+
})
|
|
25427
|
+
.then(async (r) => {
|
|
25428
|
+
const text = await r.text();
|
|
25429
|
+
if (!r.ok) { console.error('Schema search failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25430
|
+
let p; try { p = JSON.parse(text); } catch { console.log(text); return; }
|
|
25431
|
+
if (p && p.error) { console.error(String(p.error)); process.exit(1); }
|
|
25432
|
+
console.log(p.result ?? p);
|
|
25433
|
+
})
|
|
25434
|
+
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
25435
|
+
`;
|
|
25436
|
+
const resolveEntities = `#!/usr/bin/env node
|
|
25437
|
+
// Resolve named things (customers, projects, people, ...) to their real
|
|
25438
|
+
// database ids, and business concepts to table/column/join facts \u2014 one round
|
|
25439
|
+
// trip, either half optional. Call this BEFORE writing SQL about anything
|
|
25440
|
+
// named in the question; never guess or fuzzy-match a name yourself.
|
|
25441
|
+
// Generated per run \u2014 do not edit.
|
|
25442
|
+
const BRIDGE = ${JSON.stringify(opts.bridgeUrl)};
|
|
25443
|
+
|
|
25444
|
+
const [argJson] = process.argv.slice(2);
|
|
25445
|
+
if (!argJson) {
|
|
25446
|
+
console.error('usage: node ./resolve-entities \\'{"mentions":[{"text":"..."}],"entityTypes":["..."]}\\'\\nRun: node ./sources \u2014 for which entity types exist. Either field may be omitted.');
|
|
25447
|
+
process.exit(2);
|
|
25448
|
+
}
|
|
25449
|
+
let args;
|
|
25450
|
+
try { args = JSON.parse(argJson); }
|
|
25451
|
+
catch (e) { console.error('argument must be JSON: ' + String(e.message || e)); process.exit(2); }
|
|
25452
|
+
|
|
25453
|
+
fetch(BRIDGE + '/resolve-entities', {
|
|
25454
|
+
method: 'POST',
|
|
25455
|
+
headers: { 'content-type': 'application/json' },
|
|
25456
|
+
body: JSON.stringify({ mentions: args.mentions ?? [], entityTypes: args.entityTypes ?? [] }),
|
|
25457
|
+
})
|
|
25458
|
+
.then(async (r) => {
|
|
25459
|
+
const text = await r.text();
|
|
25460
|
+
if (!r.ok) { console.error('Entity resolution failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25461
|
+
let p; try { p = JSON.parse(text); } catch { console.log(text); return; }
|
|
25462
|
+
if (p && p.error) { console.error(String(p.error)); process.exit(1); }
|
|
25463
|
+
console.log(JSON.stringify(p.result ?? p, null, 2));
|
|
25464
|
+
})
|
|
25465
|
+
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
25466
|
+
`;
|
|
25467
|
+
const conceptCatalogShim = `#!/usr/bin/env node
|
|
25468
|
+
// Every verified concept \u2014 name, aliases, and what it is for. No bodies: the
|
|
25469
|
+
// whole vocabulary in one call, so you know what exists and which ones bear on
|
|
25470
|
+
// the question, instead of guessing a name into ./run-tool "concept". Read it,
|
|
25471
|
+
// then fetch the ones that apply. Call this once, early. There is no search
|
|
25472
|
+
// step and nothing to search: this is the complete list.
|
|
25473
|
+
// Generated per run \u2014 do not edit.
|
|
25474
|
+
const BRIDGE = ${JSON.stringify(opts.bridgeUrl)};
|
|
25475
|
+
|
|
25476
|
+
fetch(BRIDGE + '/concept-catalog', { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' })
|
|
25477
|
+
.then(async (r) => {
|
|
25478
|
+
const text = await r.text();
|
|
25479
|
+
if (!r.ok) { console.error('Concept catalog fetch failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25480
|
+
let p; try { p = JSON.parse(text); } catch { console.log(text); return; }
|
|
25481
|
+
if (p && p.error) { console.error(String(p.error)); process.exit(1); }
|
|
25482
|
+
console.log(JSON.stringify(p.result ?? p, null, 2));
|
|
25483
|
+
})
|
|
25484
|
+
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
24964
25485
|
`;
|
|
24965
|
-
|
|
24966
|
-
|
|
24967
|
-
|
|
24968
|
-
|
|
25486
|
+
const knowledgeBaseShim = `#!/usr/bin/env node
|
|
25487
|
+
// Free-form domain knowledge (gotchas, join paths, table/column meanings) \u2014
|
|
25488
|
+
// lower priority than the concept catalog: check ./concept-catalog / the
|
|
25489
|
+
// concept tool first for anything with a formal business-rule meaning, use
|
|
25490
|
+
// this directly for everything else.
|
|
25491
|
+
//
|
|
25492
|
+
// No args lists every node; get fetches the bodies. There is no search step
|
|
25493
|
+
// and nothing to search \u2014 the corpus is tens of nodes with one short title
|
|
25494
|
+
// each, same as ./concept-catalog. Generated per run \u2014 do not edit.
|
|
25495
|
+
const BRIDGE = ${JSON.stringify(opts.bridgeUrl)};
|
|
25496
|
+
|
|
25497
|
+
const [argJson] = process.argv.slice(2);
|
|
25498
|
+
let args;
|
|
25499
|
+
if (!argJson) {
|
|
25500
|
+
args = { method: 'catalog' };
|
|
25501
|
+
} else {
|
|
25502
|
+
try { args = JSON.parse(argJson); }
|
|
25503
|
+
catch (e) {
|
|
25504
|
+
console.error('argument must be JSON: ' + String(e.message || e));
|
|
25505
|
+
console.error('usage: node ./knowledge-base \u2192 every node: id, title, category, tags');
|
|
25506
|
+
console.error(' node ./knowledge-base \\'{"method":"get","ids":[12,31]}\\' \u2192 their content');
|
|
25507
|
+
process.exit(2);
|
|
24969
25508
|
}
|
|
24970
25509
|
}
|
|
24971
25510
|
|
|
25511
|
+
fetch(BRIDGE + '/knowledge-base', {
|
|
25512
|
+
method: 'POST',
|
|
25513
|
+
headers: { 'content-type': 'application/json' },
|
|
25514
|
+
body: JSON.stringify(args),
|
|
25515
|
+
})
|
|
25516
|
+
.then(async (r) => {
|
|
25517
|
+
const text = await r.text();
|
|
25518
|
+
if (!r.ok) { console.error('Knowledge base lookup failed (' + r.status + '): ' + text.slice(0, 2000)); process.exit(1); }
|
|
25519
|
+
let p; try { p = JSON.parse(text); } catch { console.log(text); return; }
|
|
25520
|
+
if (p && p.error) { console.error(String(p.error)); process.exit(1); }
|
|
25521
|
+
console.log(JSON.stringify(p.result ?? p, null, 2));
|
|
25522
|
+
})
|
|
25523
|
+
.catch((e) => { console.error('Could not reach the data bridge: ' + (e && e.message)); process.exit(1); });
|
|
25524
|
+
`;
|
|
25525
|
+
const sources = `#!/usr/bin/env node
|
|
25526
|
+
// The data sources you can query with ./query (and search with
|
|
25527
|
+
// ./schema-search when "searchable" is true), the pre-built tools you can
|
|
25528
|
+
// invoke with ./run-tool, and the entity types ./resolve-entities can
|
|
25529
|
+
// resolve names against. The concept catalog itself is NOT repeated here \u2014
|
|
25530
|
+
// run ./concept-catalog for that.
|
|
25531
|
+
console.log(${JSON.stringify(
|
|
25532
|
+
JSON.stringify({
|
|
25533
|
+
sources: opts.sources,
|
|
25534
|
+
directTools,
|
|
25535
|
+
entityTypes,
|
|
25536
|
+
...conceptCatalog.length ? { conceptCount: conceptCatalog.length } : {},
|
|
25537
|
+
...hasKnowledgeBase ? { knowledgeBase: true } : {}
|
|
25538
|
+
}, null, 2)
|
|
25539
|
+
)});
|
|
25540
|
+
`;
|
|
25541
|
+
const files = [
|
|
25542
|
+
["sources", sources, "(no arguments) \u2014 what you can query, which of those are searchable, the pre-built tools, and the entity types."],
|
|
25543
|
+
["query", query, '"<toolId>" "<sql>" [limit] \u2014 read-only SQL against one source. The only way to see real data. ./sources for the toolIds.']
|
|
25544
|
+
];
|
|
25545
|
+
if (opts.conceptCatalog) files.push(["concept-catalog", conceptCatalogShim, '(no arguments) \u2014 every verified concept: name, aliases, what it is for. No bodies. Read this before the schema; fetch bodies with ./run-tool "concept".']);
|
|
25546
|
+
if (hasKnowledgeBase) files.push(["knowledge-base", knowledgeBaseShim, `[ '{"method":"get","ids":[12,31]}' ] \u2014 free-form domain knowledge: gotchas, join paths, what a column really holds. No arguments lists every node; get fetches bodies. Ranks below concepts, above your own reading of the schema.`]);
|
|
25547
|
+
if (entityTypes.length) files.push(["resolve-entities", resolveEntities, `'{"mentions":[{"text":"<name>"}]}' \u2014 turn a name a person typed into the value stored in the data. Run it before filtering on any proper noun.`]);
|
|
25548
|
+
if (hasSearchableSource) files.push(["schema-search", schemaSearch, `"<toolId>" <keyword> [keyword...] \u2014 keyword search over a large source's schema. Required before writing SQL against a "searchable" source \u2014 its schema was never shown to you in full.`]);
|
|
25549
|
+
if (directTools.length) files.push(["run-tool", runTool, `"<toolId>" '<json params>' \u2014 invoke a pre-built business-logic tool, including "concept" get/run. ./sources lists each one's parameters.`]);
|
|
25550
|
+
return writeShims(
|
|
25551
|
+
files.map(([name, body, summary]) => ({ name, body, summary })),
|
|
25552
|
+
ws
|
|
25553
|
+
);
|
|
25554
|
+
}
|
|
25555
|
+
|
|
24972
25556
|
// src/codingAgent/triggers.ts
|
|
24973
25557
|
var fs10 = __toESM(require("fs"));
|
|
24974
|
-
var
|
|
25558
|
+
var path11 = __toESM(require("path"));
|
|
24975
25559
|
var EVENT_BURST_CAP = 200;
|
|
24976
25560
|
var capEvents = (events) => events.length > EVENT_BURST_CAP ? events.slice(-EVENT_BURST_CAP) : events;
|
|
24977
25561
|
function statePath2(agentId) {
|
|
24978
|
-
return
|
|
25562
|
+
return path11.join(getCodingAgentsConfig().runtimeDir, agentId, "_triggers.json");
|
|
24979
25563
|
}
|
|
24980
25564
|
function loadTriggerState(agentId) {
|
|
24981
25565
|
let raw;
|
|
@@ -25000,7 +25584,7 @@ function loadTriggerState(agentId) {
|
|
|
25000
25584
|
function saveTriggerState(agentId, state) {
|
|
25001
25585
|
try {
|
|
25002
25586
|
const p = statePath2(agentId);
|
|
25003
|
-
fs10.mkdirSync(
|
|
25587
|
+
fs10.mkdirSync(path11.dirname(p), { recursive: true });
|
|
25004
25588
|
fs10.writeFileSync(p, JSON.stringify(state, null, 2));
|
|
25005
25589
|
} catch (err) {
|
|
25006
25590
|
logger.warn(`[CodingAgent:${agentId}] failed to persist trigger state: ${err?.message ?? err}`);
|
|
@@ -25138,12 +25722,12 @@ function describeTriggers() {
|
|
|
25138
25722
|
|
|
25139
25723
|
// src/codingAgent/collection.ts
|
|
25140
25724
|
var fs11 = __toESM(require("fs"));
|
|
25141
|
-
var
|
|
25725
|
+
var path12 = __toESM(require("path"));
|
|
25142
25726
|
function isChattable(agent) {
|
|
25143
25727
|
return agent.mode !== "task";
|
|
25144
25728
|
}
|
|
25145
25729
|
function registerCodingAgentCollection(sdk, config2 = {}) {
|
|
25146
|
-
const runtimeDir = config2.runtimeDir || process.env.CODING_AGENT_RUNTIME_DIR ||
|
|
25730
|
+
const runtimeDir = config2.runtimeDir || process.env.CODING_AGENT_RUNTIME_DIR || path12.join(process.cwd(), ".coding-agent-runtime");
|
|
25147
25731
|
const defaultHarness = config2.harness || process.env.CODING_AGENT_HARNESS || "codex";
|
|
25148
25732
|
const sessions = /* @__PURE__ */ new Map();
|
|
25149
25733
|
const running = /* @__PURE__ */ new Set();
|
|
@@ -25203,7 +25787,7 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
|
|
|
25203
25787
|
...record.status === "skipped" ? { error: `${def.title} is in the middle of a run \u2014 try again in a moment.` } : record.error ? { error: record.error } : {}
|
|
25204
25788
|
};
|
|
25205
25789
|
}
|
|
25206
|
-
const cwd =
|
|
25790
|
+
const cwd = path12.join(runtimeDir, "threads", threadId);
|
|
25207
25791
|
fs11.mkdirSync(cwd, { recursive: true });
|
|
25208
25792
|
let session = sessions.get(threadId);
|
|
25209
25793
|
if (!session) {
|
|
@@ -25369,6 +25953,134 @@ async function handleCodingAgentRequest(data, collections, sendMessage) {
|
|
|
25369
25953
|
}
|
|
25370
25954
|
}
|
|
25371
25955
|
|
|
25956
|
+
// src/dashBuilder/handler.ts
|
|
25957
|
+
var inFlightAborts4 = /* @__PURE__ */ new Map();
|
|
25958
|
+
var recentlyAborted4 = /* @__PURE__ */ new Map();
|
|
25959
|
+
var ABORT_TOMBSTONE_TTL_MS4 = 3e4;
|
|
25960
|
+
function setAbortTombstone4(dashboardId) {
|
|
25961
|
+
const now = Date.now();
|
|
25962
|
+
recentlyAborted4.set(dashboardId, now);
|
|
25963
|
+
for (const [key, ts] of recentlyAborted4) {
|
|
25964
|
+
if (now - ts > ABORT_TOMBSTONE_TTL_MS4) recentlyAborted4.delete(key);
|
|
25965
|
+
}
|
|
25966
|
+
}
|
|
25967
|
+
function consumeAbortTombstone4(dashboardId) {
|
|
25968
|
+
const ts = recentlyAborted4.get(dashboardId);
|
|
25969
|
+
if (ts === void 0) return false;
|
|
25970
|
+
recentlyAborted4.delete(dashboardId);
|
|
25971
|
+
return Date.now() - ts <= ABORT_TOMBSTONE_TTL_MS4;
|
|
25972
|
+
}
|
|
25973
|
+
function handleDashBuilderAbort(data, sendMessage) {
|
|
25974
|
+
const parsed = DashBuilderAbortRequestMessageSchema.safeParse(data);
|
|
25975
|
+
if (!parsed.success) {
|
|
25976
|
+
logger.warn("[DashBuilderAbort] Invalid message \u2014 ignoring");
|
|
25977
|
+
return;
|
|
25978
|
+
}
|
|
25979
|
+
const { payload, from } = parsed.data;
|
|
25980
|
+
const { dashboardId } = payload;
|
|
25981
|
+
const controller = inFlightAborts4.get(dashboardId);
|
|
25982
|
+
if (controller) {
|
|
25983
|
+
controller.abort();
|
|
25984
|
+
inFlightAborts4.delete(dashboardId);
|
|
25985
|
+
logger.info(`[DashBuilderAbort] Aborted in-flight turn for ${dashboardId}`);
|
|
25986
|
+
} else {
|
|
25987
|
+
setAbortTombstone4(dashboardId);
|
|
25988
|
+
logger.info(`[DashBuilderAbort] No in-flight turn for ${dashboardId} \u2014 tombstoned`);
|
|
25989
|
+
}
|
|
25990
|
+
try {
|
|
25991
|
+
sendMessage({
|
|
25992
|
+
id: `dash_builder_aborted_${dashboardId}`,
|
|
25993
|
+
type: "DASH_BUILDER_ABORTED",
|
|
25994
|
+
from: { type: "data-agent" },
|
|
25995
|
+
to: { type: "runtime", id: from.id },
|
|
25996
|
+
payload: { dashboardId }
|
|
25997
|
+
});
|
|
25998
|
+
} catch (err) {
|
|
25999
|
+
logger.warn(
|
|
26000
|
+
`[DashBuilderAbort] Failed to send abort ack: ${err instanceof Error ? err.message : String(err)}`
|
|
26001
|
+
);
|
|
26002
|
+
}
|
|
26003
|
+
}
|
|
26004
|
+
async function handleDashBuilderRequest(data, collections, sendMessage) {
|
|
26005
|
+
return runWithMessageIdentity(data, () => handleDashBuilderRequestInner(data, collections, sendMessage));
|
|
26006
|
+
}
|
|
26007
|
+
async function handleDashBuilderRequestInner(data, collections, sendMessage) {
|
|
26008
|
+
const parsed = DashBuilderRequestMessageSchema.safeParse(data);
|
|
26009
|
+
if (!parsed.success) {
|
|
26010
|
+
logger.error("[DashBuilderReq] Invalid message:", JSON.stringify(parsed.error.errors));
|
|
26011
|
+
return;
|
|
26012
|
+
}
|
|
26013
|
+
const { id, payload, from } = parsed.data;
|
|
26014
|
+
const { dashboardId, text, panelId, projectId, userId } = payload;
|
|
26015
|
+
const wsId = from.id;
|
|
26016
|
+
const respond = (res) => {
|
|
26017
|
+
sendMessage({
|
|
26018
|
+
id,
|
|
26019
|
+
type: "DASH_BUILDER_RES",
|
|
26020
|
+
from: { type: "data-agent" },
|
|
26021
|
+
to: { type: "runtime", id: wsId },
|
|
26022
|
+
payload: res
|
|
26023
|
+
});
|
|
26024
|
+
};
|
|
26025
|
+
if (!collections?.["dashboard-builder-agent"]?.["prompt"]) {
|
|
26026
|
+
respond({
|
|
26027
|
+
started: false,
|
|
26028
|
+
error: "The dashboard builder is not available in this environment (collection 'dashboard-builder-agent' not registered)."
|
|
26029
|
+
});
|
|
26030
|
+
return;
|
|
26031
|
+
}
|
|
26032
|
+
const abortController = new AbortController();
|
|
26033
|
+
if (consumeAbortTombstone4(dashboardId)) {
|
|
26034
|
+
abortController.abort();
|
|
26035
|
+
logger.info(`[DashBuilderReq] ${dashboardId} was pre-aborted \u2014 starting cancelled`);
|
|
26036
|
+
}
|
|
26037
|
+
inFlightAborts4.set(dashboardId, abortController);
|
|
26038
|
+
let seq = 0;
|
|
26039
|
+
const stream = (update) => {
|
|
26040
|
+
try {
|
|
26041
|
+
sendMessage({
|
|
26042
|
+
/**
|
|
26043
|
+
* Keyed by this request's id, not by dashboardId.
|
|
26044
|
+
*
|
|
26045
|
+
* dashboardId repeats across every turn in a conversation, so a
|
|
26046
|
+
* listener that failed to clean up would keep matching future turns
|
|
26047
|
+
* forever and interleave their output. A per-request id means a
|
|
26048
|
+
* stale listener simply never matches anything again.
|
|
26049
|
+
*/
|
|
26050
|
+
id: `dash_builder_stream_${id}`,
|
|
26051
|
+
type: "DASH_BUILDER_STREAM",
|
|
26052
|
+
from: { type: "data-agent" },
|
|
26053
|
+
to: { type: "runtime", id: wsId },
|
|
26054
|
+
payload: { dashboardId, seq: seq++, update }
|
|
26055
|
+
});
|
|
26056
|
+
} catch (err) {
|
|
26057
|
+
logger.warn(
|
|
26058
|
+
`[DashBuilderReq] Stream send failed (socket may be closed): ${err instanceof Error ? err.message : String(err)}`
|
|
26059
|
+
);
|
|
26060
|
+
}
|
|
26061
|
+
};
|
|
26062
|
+
try {
|
|
26063
|
+
const result = await collections["dashboard-builder-agent"]["prompt"]({
|
|
26064
|
+
dashboardId,
|
|
26065
|
+
text,
|
|
26066
|
+
panelId,
|
|
26067
|
+
projectId,
|
|
26068
|
+
userId,
|
|
26069
|
+
signal: abortController.signal,
|
|
26070
|
+
onUpdate: stream
|
|
26071
|
+
});
|
|
26072
|
+
respond(result ?? { started: true });
|
|
26073
|
+
} catch (err) {
|
|
26074
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
26075
|
+
logger.error(`[DashBuilderReq] ${dashboardId} failed to start: ${message}`);
|
|
26076
|
+
respond({ started: false, error: message });
|
|
26077
|
+
} finally {
|
|
26078
|
+
if (inFlightAborts4.get(dashboardId) === abortController) {
|
|
26079
|
+
inFlightAborts4.delete(dashboardId);
|
|
26080
|
+
}
|
|
26081
|
+
}
|
|
26082
|
+
}
|
|
26083
|
+
|
|
25372
26084
|
// src/reportComp/types.ts
|
|
25373
26085
|
var DEFAULT_REPORT_COMP_MODELS = {
|
|
25374
26086
|
anthropic: "anthropic/claude-haiku-4-5-20251001",
|
|
@@ -25867,21 +26579,21 @@ Fixed SQL query:`;
|
|
|
25867
26579
|
}
|
|
25868
26580
|
|
|
25869
26581
|
// src/reportComp/index.ts
|
|
25870
|
-
var
|
|
25871
|
-
var
|
|
25872
|
-
var
|
|
25873
|
-
function
|
|
26582
|
+
var inFlightAborts5 = /* @__PURE__ */ new Map();
|
|
26583
|
+
var recentlyAborted5 = /* @__PURE__ */ new Map();
|
|
26584
|
+
var ABORT_TOMBSTONE_TTL_MS5 = 3e4;
|
|
26585
|
+
function setAbortTombstone5(reportId) {
|
|
25874
26586
|
const now = Date.now();
|
|
25875
|
-
|
|
25876
|
-
for (const [key, ts] of
|
|
25877
|
-
if (now - ts >
|
|
26587
|
+
recentlyAborted5.set(reportId, now);
|
|
26588
|
+
for (const [key, ts] of recentlyAborted5) {
|
|
26589
|
+
if (now - ts > ABORT_TOMBSTONE_TTL_MS5) recentlyAborted5.delete(key);
|
|
25878
26590
|
}
|
|
25879
26591
|
}
|
|
25880
|
-
function
|
|
25881
|
-
const ts =
|
|
26592
|
+
function consumeAbortTombstone5(reportId) {
|
|
26593
|
+
const ts = recentlyAborted5.get(reportId);
|
|
25882
26594
|
if (ts === void 0) return false;
|
|
25883
|
-
|
|
25884
|
-
return Date.now() - ts <=
|
|
26595
|
+
recentlyAborted5.delete(reportId);
|
|
26596
|
+
return Date.now() - ts <= ABORT_TOMBSTONE_TTL_MS5;
|
|
25885
26597
|
}
|
|
25886
26598
|
function handleReportCompAbort(data, sendMessage) {
|
|
25887
26599
|
const parseResult = ReportCompAbortRequestMessageSchema.safeParse(data);
|
|
@@ -25892,13 +26604,13 @@ function handleReportCompAbort(data, sendMessage) {
|
|
|
25892
26604
|
const { payload, from } = parseResult.data;
|
|
25893
26605
|
const { reportId } = payload;
|
|
25894
26606
|
const wsId = from.id;
|
|
25895
|
-
const controller =
|
|
26607
|
+
const controller = inFlightAborts5.get(reportId);
|
|
25896
26608
|
if (controller) {
|
|
25897
26609
|
controller.abort();
|
|
25898
|
-
|
|
26610
|
+
inFlightAborts5.delete(reportId);
|
|
25899
26611
|
logger.info(`[ReportCompAbort] Aborted in-flight run for report ${reportId}`);
|
|
25900
26612
|
} else {
|
|
25901
|
-
|
|
26613
|
+
setAbortTombstone5(reportId);
|
|
25902
26614
|
logger.info(`[ReportCompAbort] No in-flight run for report ${reportId} \u2014 tombstoned`);
|
|
25903
26615
|
}
|
|
25904
26616
|
try {
|
|
@@ -25944,11 +26656,11 @@ var processReportCompRequest = async (data, components, _sendMessage, anthropicA
|
|
|
25944
26656
|
const trace = createRunTrace();
|
|
25945
26657
|
const abortController = new AbortController();
|
|
25946
26658
|
if (reportId) {
|
|
25947
|
-
if (
|
|
26659
|
+
if (consumeAbortTombstone5(reportId)) {
|
|
25948
26660
|
abortController.abort();
|
|
25949
26661
|
logger.info(`[REPORT_COMP_REQ] reportId=${reportId} was pre-aborted \u2014 starting cancelled`);
|
|
25950
26662
|
}
|
|
25951
|
-
|
|
26663
|
+
inFlightAborts5.set(reportId, abortController);
|
|
25952
26664
|
}
|
|
25953
26665
|
let llmResponse;
|
|
25954
26666
|
try {
|
|
@@ -25969,7 +26681,7 @@ var processReportCompRequest = async (data, components, _sendMessage, anthropicA
|
|
|
25969
26681
|
trace
|
|
25970
26682
|
);
|
|
25971
26683
|
} finally {
|
|
25972
|
-
if (reportId)
|
|
26684
|
+
if (reportId) inFlightAborts5.delete(reportId);
|
|
25973
26685
|
}
|
|
25974
26686
|
const wasAborted = abortController.signal.aborted || !llmResponse.success && Array.isArray(llmResponse.errors) && llmResponse.errors.includes("aborted");
|
|
25975
26687
|
if (wasAborted) {
|
|
@@ -27678,16 +28390,16 @@ function buildDashboardAgentTools(sdk, signal, trace) {
|
|
|
27678
28390
|
}
|
|
27679
28391
|
|
|
27680
28392
|
// src/dashboardAgent/collection.ts
|
|
27681
|
-
var
|
|
27682
|
-
var
|
|
27683
|
-
function
|
|
27684
|
-
if (!
|
|
27685
|
-
return
|
|
27686
|
-
}
|
|
27687
|
-
var
|
|
27688
|
-
function
|
|
27689
|
-
if (!
|
|
27690
|
-
|
|
28393
|
+
var dynamicImport3 = new Function("specifier", "return import(specifier)");
|
|
28394
|
+
var piModulePromise2 = null;
|
|
28395
|
+
function loadPi2() {
|
|
28396
|
+
if (!piModulePromise2) piModulePromise2 = dynamicImport3("@earendil-works/pi-coding-agent");
|
|
28397
|
+
return piModulePromise2;
|
|
28398
|
+
}
|
|
28399
|
+
var authAndRegistry2 = null;
|
|
28400
|
+
function getAuthAndRegistry2() {
|
|
28401
|
+
if (!authAndRegistry2) {
|
|
28402
|
+
authAndRegistry2 = loadPi2().then(({ AuthStorage, ModelRegistry }) => {
|
|
27691
28403
|
const authStorage = AuthStorage.create();
|
|
27692
28404
|
const modelRegistry = ModelRegistry.create(authStorage);
|
|
27693
28405
|
const proxyRoot = process.env.SUPERATOM_LLM_PROXY_URL;
|
|
@@ -27704,7 +28416,7 @@ function getAuthAndRegistry() {
|
|
|
27704
28416
|
return { authStorage, modelRegistry };
|
|
27705
28417
|
});
|
|
27706
28418
|
}
|
|
27707
|
-
return
|
|
28419
|
+
return authAndRegistry2;
|
|
27708
28420
|
}
|
|
27709
28421
|
async function preResolveSchema(sdk, tool, intent, projectId) {
|
|
27710
28422
|
const tier = tool.schemaTier;
|
|
@@ -27917,8 +28629,8 @@ ${fullPrompt}
|
|
|
27917
28629
|
return { success: false, error: "aborted" };
|
|
27918
28630
|
}
|
|
27919
28631
|
try {
|
|
27920
|
-
const { createAgentSession, SessionManager } = await
|
|
27921
|
-
const { authStorage, modelRegistry } = await
|
|
28632
|
+
const { createAgentSession, SessionManager } = await loadPi2();
|
|
28633
|
+
const { authStorage, modelRegistry } = await getAuthAndRegistry2();
|
|
27922
28634
|
let model;
|
|
27923
28635
|
const explicitProvider = config2.provider || process.env.PI_AGENT_PROVIDER;
|
|
27924
28636
|
const explicitModel = config2.model || process.env.PI_AGENT_MODEL;
|
|
@@ -28316,6 +29028,15 @@ var SuperatomSDK = class {
|
|
|
28316
29028
|
// since an outage of unknown length shouldn't grow this without limit.
|
|
28317
29029
|
this.pendingOutbox = [];
|
|
28318
29030
|
this.MAX_OUTBOX_SIZE = 50;
|
|
29031
|
+
/**
|
|
29032
|
+
* The dashboard contract, as registered by the browser bundle that holds it.
|
|
29033
|
+
*
|
|
29034
|
+
* Empty until a client has connected and pushed it. That is a real state and
|
|
29035
|
+
* callers must handle it rather than treat it as an empty contract: an empty
|
|
29036
|
+
* list means "nobody has told us yet", not "there are no components", and
|
|
29037
|
+
* building against it would produce a dashboard that can import nothing.
|
|
29038
|
+
*/
|
|
29039
|
+
this.dashContract = [];
|
|
28319
29040
|
if (config2.logLevel) {
|
|
28320
29041
|
logger.setLogLevel(config2.logLevel);
|
|
28321
29042
|
}
|
|
@@ -28432,7 +29153,7 @@ var SuperatomSDK = class {
|
|
|
28432
29153
|
logger.info("Already connected to WebSocket");
|
|
28433
29154
|
return Promise.resolve();
|
|
28434
29155
|
}
|
|
28435
|
-
return new Promise((
|
|
29156
|
+
return new Promise((resolve3, reject) => {
|
|
28436
29157
|
try {
|
|
28437
29158
|
const url = new URL(this.url);
|
|
28438
29159
|
if (this.apiKey) {
|
|
@@ -28448,7 +29169,7 @@ var SuperatomSDK = class {
|
|
|
28448
29169
|
logger.info("WebSocket connected successfully");
|
|
28449
29170
|
this.startHeartbeat();
|
|
28450
29171
|
this.flushPendingOutbox();
|
|
28451
|
-
|
|
29172
|
+
resolve3();
|
|
28452
29173
|
});
|
|
28453
29174
|
this.ws.addEventListener("message", (event) => {
|
|
28454
29175
|
this.handleMessage(event.data);
|
|
@@ -28536,6 +29257,13 @@ var SuperatomSDK = class {
|
|
|
28536
29257
|
logger.error("Failed to handle component list request:", error);
|
|
28537
29258
|
});
|
|
28538
29259
|
break;
|
|
29260
|
+
/* The dashboard contract, pushed by the bundle that holds it — on
|
|
29261
|
+
* connect and again on every reconnect. See types.ts. */
|
|
29262
|
+
case "DASH_CONTRACT_RES":
|
|
29263
|
+
handleDashContractResponse(parsed, (c) => this.storeDashContract(c), this.collections).catch((error) => {
|
|
29264
|
+
logger.error("Failed to handle dashboard contract:", error);
|
|
29265
|
+
});
|
|
29266
|
+
break;
|
|
28539
29267
|
case "WORKFLOW_LIST_RES":
|
|
28540
29268
|
handleWorkflowListResponse(parsed, (wf) => this.setWorkflows(wf)).catch((error) => {
|
|
28541
29269
|
logger.error("Failed to handle workflow list request:", error);
|
|
@@ -28602,6 +29330,16 @@ var SuperatomSDK = class {
|
|
|
28602
29330
|
case "CODING_AGENT_ABORT_REQ":
|
|
28603
29331
|
handleCodingAgentAbort(parsed, (msg) => this.send(msg));
|
|
28604
29332
|
break;
|
|
29333
|
+
// The dashboard BUILDER's conversation — distinct from
|
|
29334
|
+
// DASHBOARD_AGENT_REQ, which drives the older JSON-DSL flow.
|
|
29335
|
+
case "DASH_BUILDER_REQ":
|
|
29336
|
+
handleDashBuilderRequest(parsed, this.collections, (msg) => this.send(msg)).catch((error) => {
|
|
29337
|
+
logger.error("Failed to handle dash builder request:", error);
|
|
29338
|
+
});
|
|
29339
|
+
break;
|
|
29340
|
+
case "DASH_BUILDER_ABORT_REQ":
|
|
29341
|
+
handleDashBuilderAbort(parsed, (msg) => this.send(msg));
|
|
29342
|
+
break;
|
|
28605
29343
|
case "REPORT_COMP_REQ":
|
|
28606
29344
|
handleReportCompRequest(parsed, this.components, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders, this.collections, this.tools, this.dashCompModels).catch((error) => {
|
|
28607
29345
|
logger.error("Failed to handle report comp request:", error);
|
|
@@ -28824,6 +29562,14 @@ var SuperatomSDK = class {
|
|
|
28824
29562
|
getComponents() {
|
|
28825
29563
|
return this.components;
|
|
28826
29564
|
}
|
|
29565
|
+
storeDashContract(components) {
|
|
29566
|
+
this.dashContract = components;
|
|
29567
|
+
logger.info(`Dashboard contract registered: ${components.length} components`);
|
|
29568
|
+
}
|
|
29569
|
+
/** The registered dashboard contract. Empty means "not registered yet". */
|
|
29570
|
+
getDashContract() {
|
|
29571
|
+
return this.dashContract;
|
|
29572
|
+
}
|
|
28827
29573
|
/**
|
|
28828
29574
|
* Set tools for the SDK instance
|
|
28829
29575
|
*/
|
|
@@ -28946,11 +29692,13 @@ var SuperatomSDK = class {
|
|
|
28946
29692
|
UIBlock,
|
|
28947
29693
|
UILogCollector,
|
|
28948
29694
|
UserManager,
|
|
29695
|
+
analyticsClient,
|
|
28949
29696
|
answerCatalogForBinding,
|
|
28950
29697
|
answerComponents,
|
|
28951
29698
|
anthropicLLM,
|
|
28952
29699
|
assertReadOnlySql,
|
|
28953
29700
|
bindContext,
|
|
29701
|
+
bridgePreamble,
|
|
28954
29702
|
captureContext,
|
|
28955
29703
|
clearContextTokens,
|
|
28956
29704
|
contextTokenCount,
|
|
@@ -28966,6 +29714,7 @@ var SuperatomSDK = class {
|
|
|
28966
29714
|
geminiLLM,
|
|
28967
29715
|
getCodingAgent,
|
|
28968
29716
|
getCodingAgentsConfig,
|
|
29717
|
+
getPiSessionState,
|
|
28969
29718
|
getRequestContext,
|
|
28970
29719
|
groqLLM,
|
|
28971
29720
|
hybridRerank,
|
|
@@ -28978,9 +29727,11 @@ var SuperatomSDK = class {
|
|
|
28978
29727
|
mintContextToken,
|
|
28979
29728
|
normalizeScriptBody,
|
|
28980
29729
|
onAgentRun,
|
|
29730
|
+
onPiSessionUpdate,
|
|
28981
29731
|
openaiLLM,
|
|
28982
29732
|
policiesFromConfig,
|
|
28983
29733
|
projectForDatasetBinding,
|
|
29734
|
+
promptLoader,
|
|
28984
29735
|
queryCache,
|
|
28985
29736
|
registerCodingAgentCollection,
|
|
28986
29737
|
registerCodingAgents,
|
|
@@ -29002,6 +29753,7 @@ var SuperatomSDK = class {
|
|
|
29002
29753
|
userPromptErrorLogger,
|
|
29003
29754
|
validateComponentSpec,
|
|
29004
29755
|
withCapturedContext,
|
|
29005
|
-
writeBridgeShims
|
|
29756
|
+
writeBridgeShims,
|
|
29757
|
+
writeShims
|
|
29006
29758
|
});
|
|
29007
29759
|
//# sourceMappingURL=index.js.map
|