hankweave 0.2.1 → 0.2.3
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/dist/index.js +218 -203
- package/dist/index.js.map +67 -10
- package/dist/shims/codex/index.js +203 -26
- package/package.json +3 -2
- package/schemas/hankweave.schema.json +20 -0
- package/shims/codex/index.js +203 -26
|
@@ -145,7 +145,7 @@ async function runSelfTest() {
|
|
|
145
145
|
import * as fs4 from "fs";
|
|
146
146
|
import * as path4 from "path";
|
|
147
147
|
|
|
148
|
-
// ../../node_modules/.bun/@openai+codex-sdk@0.
|
|
148
|
+
// ../../node_modules/.bun/@openai+codex-sdk@0.98.0/node_modules/@openai/codex-sdk/dist/index.js
|
|
149
149
|
import { promises as fs2 } from "fs";
|
|
150
150
|
import os2 from "os";
|
|
151
151
|
import path2 from "path";
|
|
@@ -218,6 +218,7 @@ var Thread = class {
|
|
|
218
218
|
modelReasoningEffort: options?.modelReasoningEffort,
|
|
219
219
|
signal: turnOptions.signal,
|
|
220
220
|
networkAccessEnabled: options?.networkAccessEnabled,
|
|
221
|
+
webSearchMode: options?.webSearchMode,
|
|
221
222
|
webSearchEnabled: options?.webSearchEnabled,
|
|
222
223
|
approvalPolicy: options?.approvalPolicy,
|
|
223
224
|
additionalDirectories: options?.additionalDirectories
|
|
@@ -285,12 +286,19 @@ var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts";
|
|
|
285
286
|
var CodexExec = class {
|
|
286
287
|
executablePath;
|
|
287
288
|
envOverride;
|
|
288
|
-
|
|
289
|
+
configOverrides;
|
|
290
|
+
constructor(executablePath = null, env, configOverrides) {
|
|
289
291
|
this.executablePath = executablePath || findCodexPath();
|
|
290
292
|
this.envOverride = env;
|
|
293
|
+
this.configOverrides = configOverrides;
|
|
291
294
|
}
|
|
292
295
|
async *run(args) {
|
|
293
296
|
const commandArgs = ["exec", "--experimental-json"];
|
|
297
|
+
if (this.configOverrides) {
|
|
298
|
+
for (const override of serializeConfigOverrides(this.configOverrides)) {
|
|
299
|
+
commandArgs.push("--config", override);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
294
302
|
if (args.model) {
|
|
295
303
|
commandArgs.push("--model", args.model);
|
|
296
304
|
}
|
|
@@ -320,20 +328,24 @@ var CodexExec = class {
|
|
|
320
328
|
`sandbox_workspace_write.network_access=${args.networkAccessEnabled}`
|
|
321
329
|
);
|
|
322
330
|
}
|
|
323
|
-
if (args.
|
|
324
|
-
commandArgs.push("--config", `
|
|
331
|
+
if (args.webSearchMode) {
|
|
332
|
+
commandArgs.push("--config", `web_search="${args.webSearchMode}"`);
|
|
333
|
+
} else if (args.webSearchEnabled === true) {
|
|
334
|
+
commandArgs.push("--config", `web_search="live"`);
|
|
335
|
+
} else if (args.webSearchEnabled === false) {
|
|
336
|
+
commandArgs.push("--config", `web_search="disabled"`);
|
|
325
337
|
}
|
|
326
338
|
if (args.approvalPolicy) {
|
|
327
339
|
commandArgs.push("--config", `approval_policy="${args.approvalPolicy}"`);
|
|
328
340
|
}
|
|
341
|
+
if (args.threadId) {
|
|
342
|
+
commandArgs.push("resume", args.threadId);
|
|
343
|
+
}
|
|
329
344
|
if (args.images?.length) {
|
|
330
345
|
for (const image of args.images) {
|
|
331
346
|
commandArgs.push("--image", image);
|
|
332
347
|
}
|
|
333
348
|
}
|
|
334
|
-
if (args.threadId) {
|
|
335
|
-
commandArgs.push("resume", args.threadId);
|
|
336
|
-
}
|
|
337
349
|
const env = {};
|
|
338
350
|
if (this.envOverride) {
|
|
339
351
|
Object.assign(env, this.envOverride);
|
|
@@ -407,6 +419,82 @@ var CodexExec = class {
|
|
|
407
419
|
}
|
|
408
420
|
}
|
|
409
421
|
};
|
|
422
|
+
function serializeConfigOverrides(configOverrides) {
|
|
423
|
+
const overrides = [];
|
|
424
|
+
flattenConfigOverrides(configOverrides, "", overrides);
|
|
425
|
+
return overrides;
|
|
426
|
+
}
|
|
427
|
+
function flattenConfigOverrides(value, prefix, overrides) {
|
|
428
|
+
if (!isPlainObject(value)) {
|
|
429
|
+
if (prefix) {
|
|
430
|
+
overrides.push(`${prefix}=${toTomlValue(value, prefix)}`);
|
|
431
|
+
return;
|
|
432
|
+
} else {
|
|
433
|
+
throw new Error("Codex config overrides must be a plain object");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const entries = Object.entries(value);
|
|
437
|
+
if (!prefix && entries.length === 0) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (prefix && entries.length === 0) {
|
|
441
|
+
overrides.push(`${prefix}={}`);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
for (const [key, child] of entries) {
|
|
445
|
+
if (!key) {
|
|
446
|
+
throw new Error("Codex config override keys must be non-empty strings");
|
|
447
|
+
}
|
|
448
|
+
if (child === void 0) {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
const path32 = prefix ? `${prefix}.${key}` : key;
|
|
452
|
+
if (isPlainObject(child)) {
|
|
453
|
+
flattenConfigOverrides(child, path32, overrides);
|
|
454
|
+
} else {
|
|
455
|
+
overrides.push(`${path32}=${toTomlValue(child, path32)}`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function toTomlValue(value, path32) {
|
|
460
|
+
if (typeof value === "string") {
|
|
461
|
+
return JSON.stringify(value);
|
|
462
|
+
} else if (typeof value === "number") {
|
|
463
|
+
if (!Number.isFinite(value)) {
|
|
464
|
+
throw new Error(`Codex config override at ${path32} must be a finite number`);
|
|
465
|
+
}
|
|
466
|
+
return `${value}`;
|
|
467
|
+
} else if (typeof value === "boolean") {
|
|
468
|
+
return value ? "true" : "false";
|
|
469
|
+
} else if (Array.isArray(value)) {
|
|
470
|
+
const rendered = value.map((item, index) => toTomlValue(item, `${path32}[${index}]`));
|
|
471
|
+
return `[${rendered.join(", ")}]`;
|
|
472
|
+
} else if (isPlainObject(value)) {
|
|
473
|
+
const parts = [];
|
|
474
|
+
for (const [key, child] of Object.entries(value)) {
|
|
475
|
+
if (!key) {
|
|
476
|
+
throw new Error("Codex config override keys must be non-empty strings");
|
|
477
|
+
}
|
|
478
|
+
if (child === void 0) {
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
parts.push(`${formatTomlKey(key)} = ${toTomlValue(child, `${path32}.${key}`)}`);
|
|
482
|
+
}
|
|
483
|
+
return `{${parts.join(", ")}}`;
|
|
484
|
+
} else if (value === null) {
|
|
485
|
+
throw new Error(`Codex config override at ${path32} cannot be null`);
|
|
486
|
+
} else {
|
|
487
|
+
const typeName = typeof value;
|
|
488
|
+
throw new Error(`Unsupported Codex config override value at ${path32}: ${typeName}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
var TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;
|
|
492
|
+
function formatTomlKey(key) {
|
|
493
|
+
return TOML_BARE_KEY.test(key) ? key : JSON.stringify(key);
|
|
494
|
+
}
|
|
495
|
+
function isPlainObject(value) {
|
|
496
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
497
|
+
}
|
|
410
498
|
var scriptFileName = fileURLToPath(import.meta.url);
|
|
411
499
|
var scriptDirName = path22.dirname(scriptFileName);
|
|
412
500
|
function findCodexPath() {
|
|
@@ -466,7 +554,8 @@ var Codex = class {
|
|
|
466
554
|
exec;
|
|
467
555
|
options;
|
|
468
556
|
constructor(options = {}) {
|
|
469
|
-
|
|
557
|
+
const { codexPathOverride, env, config } = options;
|
|
558
|
+
this.exec = new CodexExec(codexPathOverride, env, config);
|
|
470
559
|
this.options = options;
|
|
471
560
|
}
|
|
472
561
|
/**
|
|
@@ -632,6 +721,27 @@ function getCodexModelId(spec) {
|
|
|
632
721
|
return spec.modelID;
|
|
633
722
|
}
|
|
634
723
|
|
|
724
|
+
// Model resolution assertions - verify reasoning effort parsing at load time
|
|
725
|
+
{
|
|
726
|
+
const testCases = [
|
|
727
|
+
{ input: "gpt-5.3-codex-high", expectedModelID: "gpt-5.3-codex", expectedEffort: "high" },
|
|
728
|
+
{ input: "gpt-5.3-codex-xhigh", expectedModelID: "gpt-5.3-codex", expectedEffort: "xhigh" },
|
|
729
|
+
{ input: "gpt-5.2-codex-high", expectedModelID: "gpt-5.2-codex", expectedEffort: "high" },
|
|
730
|
+
{ input: "gpt-5.2-xhigh", expectedModelID: "gpt-5.2", expectedEffort: "xhigh" },
|
|
731
|
+
{ input: "gpt-5.3-codex", expectedModelID: "gpt-5.3-codex", expectedEffort: undefined },
|
|
732
|
+
];
|
|
733
|
+
for (const tc of testCases) {
|
|
734
|
+
const result = resolveModel(tc.input);
|
|
735
|
+
if (result.modelID !== tc.expectedModelID || result.reasoningEffort !== tc.expectedEffort) {
|
|
736
|
+
throw new Error(
|
|
737
|
+
`Model resolution assertion failed for "${tc.input}": ` +
|
|
738
|
+
`expected modelID="${tc.expectedModelID}" effort="${tc.expectedEffort}", ` +
|
|
739
|
+
`got modelID="${result.modelID}" effort="${result.reasoningEffort}"`
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
635
745
|
// src/utils/output.ts
|
|
636
746
|
function emit(message) {
|
|
637
747
|
console.log(JSON.stringify(message));
|
|
@@ -793,6 +903,8 @@ var CodexShim = class {
|
|
|
793
903
|
},
|
|
794
904
|
workStarted: false,
|
|
795
905
|
hasReceivedDeltas: false,
|
|
906
|
+
lastEmittedAssistantText: "",
|
|
907
|
+
lastEmittedReasoningByItemId: /* @__PURE__ */ new Map(),
|
|
796
908
|
emittedToolIds: /* @__PURE__ */ new Set(),
|
|
797
909
|
toolIdMapping: /* @__PURE__ */ new Map()
|
|
798
910
|
};
|
|
@@ -864,7 +976,7 @@ ${this.args.appendSystemPrompt}`;
|
|
|
864
976
|
this.apiStartTime = state.apiStartTime;
|
|
865
977
|
const { events } = await state.thread.runStreamed(finalPrompt);
|
|
866
978
|
const currentMessageContent = [];
|
|
867
|
-
|
|
979
|
+
let currentMessageId = generateMessageId();
|
|
868
980
|
const pendingToolResults = /* @__PURE__ */ new Map();
|
|
869
981
|
let systemInitEmitted = false;
|
|
870
982
|
for await (const event of events) {
|
|
@@ -908,10 +1020,11 @@ ${this.args.appendSystemPrompt}`;
|
|
|
908
1020
|
currentMessageContent,
|
|
909
1021
|
pendingToolResults,
|
|
910
1022
|
model,
|
|
1023
|
+
currentMessageId,
|
|
911
1024
|
event.type === "item.completed"
|
|
912
1025
|
);
|
|
913
1026
|
break;
|
|
914
|
-
case "turn.completed":
|
|
1027
|
+
case "turn.completed": {
|
|
915
1028
|
if (event.usage) {
|
|
916
1029
|
state.totalUsage.input_tokens += event.usage.input_tokens;
|
|
917
1030
|
state.totalUsage.output_tokens += event.usage.output_tokens;
|
|
@@ -920,11 +1033,12 @@ ${this.args.appendSystemPrompt}`;
|
|
|
920
1033
|
}
|
|
921
1034
|
}
|
|
922
1035
|
verboseLog(this.args.verbose, "Turn completed", event.usage);
|
|
923
|
-
|
|
1036
|
+
const completionContent = state.hasReceivedDeltas ? [] : currentMessageContent;
|
|
1037
|
+
if (completionContent.length > 0 || event.usage) {
|
|
924
1038
|
this.emitAssistantMessage(
|
|
925
1039
|
currentMessageId,
|
|
926
1040
|
model,
|
|
927
|
-
|
|
1041
|
+
completionContent,
|
|
928
1042
|
event.usage,
|
|
929
1043
|
"end_turn"
|
|
930
1044
|
);
|
|
@@ -933,7 +1047,13 @@ ${this.args.appendSystemPrompt}`;
|
|
|
933
1047
|
this.emitToolResult(result);
|
|
934
1048
|
}
|
|
935
1049
|
pendingToolResults.clear();
|
|
1050
|
+
currentMessageContent.length = 0;
|
|
1051
|
+
state.hasReceivedDeltas = false;
|
|
1052
|
+
state.lastEmittedAssistantText = "";
|
|
1053
|
+
state.lastEmittedReasoningByItemId.clear();
|
|
1054
|
+
currentMessageId = generateMessageId();
|
|
936
1055
|
break;
|
|
1056
|
+
}
|
|
937
1057
|
case "turn.failed":
|
|
938
1058
|
verboseLog(this.args.verbose, "Turn failed:", event.error);
|
|
939
1059
|
if (this.args.debugDir) {
|
|
@@ -958,10 +1078,23 @@ ${this.args.appendSystemPrompt}`;
|
|
|
958
1078
|
this.createRawLogFile(state.sessionId);
|
|
959
1079
|
}
|
|
960
1080
|
}
|
|
961
|
-
handleItemEvent(item, state, currentMessageContent, pendingToolResults,
|
|
1081
|
+
handleItemEvent(item, state, currentMessageContent, pendingToolResults, model, currentMessageId, _isCompleted = false) {
|
|
962
1082
|
switch (item.type) {
|
|
963
1083
|
case "agent_message":
|
|
964
|
-
if (item.text
|
|
1084
|
+
if (item.text) {
|
|
1085
|
+
const previousText = state.lastEmittedAssistantText || "";
|
|
1086
|
+
const deltaText = item.text.startsWith(previousText) ? item.text.slice(previousText.length) : item.text;
|
|
1087
|
+
if (deltaText) {
|
|
1088
|
+
this.emitAssistantMessage(
|
|
1089
|
+
currentMessageId,
|
|
1090
|
+
model,
|
|
1091
|
+
[{ type: "text", text: deltaText }],
|
|
1092
|
+
void 0,
|
|
1093
|
+
null
|
|
1094
|
+
);
|
|
1095
|
+
state.hasReceivedDeltas = true;
|
|
1096
|
+
}
|
|
1097
|
+
state.lastEmittedAssistantText = item.text;
|
|
965
1098
|
const existing = currentMessageContent.find((c) => c.type === "text");
|
|
966
1099
|
if (existing && existing.type === "text") {
|
|
967
1100
|
existing.text = item.text;
|
|
@@ -972,31 +1105,69 @@ ${this.args.appendSystemPrompt}`;
|
|
|
972
1105
|
break;
|
|
973
1106
|
case "reasoning":
|
|
974
1107
|
if (item.text) {
|
|
1108
|
+
const reasoningItemId = item.id || "reasoning";
|
|
1109
|
+
const previousReasoning = state.lastEmittedReasoningByItemId.get(reasoningItemId) || "";
|
|
1110
|
+
const deltaThinking = item.text.startsWith(previousReasoning) ? item.text.slice(previousReasoning.length) : item.text;
|
|
1111
|
+
if (deltaThinking) {
|
|
1112
|
+
this.emitAssistantMessage(
|
|
1113
|
+
currentMessageId,
|
|
1114
|
+
model,
|
|
1115
|
+
[{ type: "thinking", thinking: deltaThinking }],
|
|
1116
|
+
void 0,
|
|
1117
|
+
null
|
|
1118
|
+
);
|
|
1119
|
+
state.hasReceivedDeltas = true;
|
|
1120
|
+
}
|
|
1121
|
+
state.lastEmittedReasoningByItemId.set(reasoningItemId, item.text);
|
|
975
1122
|
currentMessageContent.push({ type: "thinking", thinking: item.text });
|
|
976
1123
|
}
|
|
977
1124
|
break;
|
|
978
1125
|
case "command_execution":
|
|
979
|
-
this.handleCommandExecution(
|
|
1126
|
+
this.handleCommandExecution(
|
|
1127
|
+
item,
|
|
1128
|
+
state,
|
|
1129
|
+
currentMessageContent,
|
|
1130
|
+
pendingToolResults,
|
|
1131
|
+
model,
|
|
1132
|
+
currentMessageId
|
|
1133
|
+
);
|
|
980
1134
|
break;
|
|
981
1135
|
case "mcp_tool_call":
|
|
982
|
-
this.handleMcpToolCall(
|
|
1136
|
+
this.handleMcpToolCall(
|
|
1137
|
+
item,
|
|
1138
|
+
state,
|
|
1139
|
+
currentMessageContent,
|
|
1140
|
+
pendingToolResults,
|
|
1141
|
+
model,
|
|
1142
|
+
currentMessageId
|
|
1143
|
+
);
|
|
983
1144
|
break;
|
|
984
1145
|
case "file_change":
|
|
985
|
-
this.handleFileChange(
|
|
1146
|
+
this.handleFileChange(
|
|
1147
|
+
item,
|
|
1148
|
+
state,
|
|
1149
|
+
currentMessageContent,
|
|
1150
|
+
pendingToolResults,
|
|
1151
|
+
model,
|
|
1152
|
+
currentMessageId
|
|
1153
|
+
);
|
|
986
1154
|
break;
|
|
987
1155
|
}
|
|
988
1156
|
}
|
|
989
|
-
handleCommandExecution(item, state, currentMessageContent, pendingToolResults) {
|
|
1157
|
+
handleCommandExecution(item, state, currentMessageContent, pendingToolResults, model, currentMessageId) {
|
|
990
1158
|
if (!state.emittedToolIds.has(item.id)) {
|
|
991
1159
|
const toolUseId2 = generateToolUseId();
|
|
992
1160
|
state.emittedToolIds.add(item.id);
|
|
993
1161
|
state.toolIdMapping.set(item.id, toolUseId2);
|
|
994
|
-
|
|
1162
|
+
const toolUse = {
|
|
995
1163
|
type: "tool_use",
|
|
996
1164
|
id: toolUseId2,
|
|
997
1165
|
name: "Bash",
|
|
998
1166
|
input: { command: item.command }
|
|
999
|
-
}
|
|
1167
|
+
};
|
|
1168
|
+
currentMessageContent.push(toolUse);
|
|
1169
|
+
this.emitAssistantMessage(currentMessageId, model, [toolUse], void 0, null);
|
|
1170
|
+
state.hasReceivedDeltas = true;
|
|
1000
1171
|
}
|
|
1001
1172
|
const toolUseId = state.toolIdMapping.get(item.id);
|
|
1002
1173
|
if (!toolUseId) return;
|
|
@@ -1012,18 +1183,21 @@ ${this.args.appendSystemPrompt}`;
|
|
|
1012
1183
|
content: item.status === "failed" ? { is_error: true, error: content } : content
|
|
1013
1184
|
});
|
|
1014
1185
|
}
|
|
1015
|
-
handleMcpToolCall(item, state, currentMessageContent, pendingToolResults) {
|
|
1186
|
+
handleMcpToolCall(item, state, currentMessageContent, pendingToolResults, model, currentMessageId) {
|
|
1016
1187
|
if (!state.emittedToolIds.has(item.id)) {
|
|
1017
1188
|
const toolUseId2 = generateToolUseId();
|
|
1018
1189
|
state.emittedToolIds.add(item.id);
|
|
1019
1190
|
state.toolIdMapping.set(item.id, toolUseId2);
|
|
1020
1191
|
const toolName = normalizeToolName(item.tool);
|
|
1021
|
-
|
|
1192
|
+
const toolUse = {
|
|
1022
1193
|
type: "tool_use",
|
|
1023
1194
|
id: toolUseId2,
|
|
1024
1195
|
name: toolName,
|
|
1025
1196
|
input: normalizeToolInput(item.arguments || {})
|
|
1026
|
-
}
|
|
1197
|
+
};
|
|
1198
|
+
currentMessageContent.push(toolUse);
|
|
1199
|
+
this.emitAssistantMessage(currentMessageId, model, [toolUse], void 0, null);
|
|
1200
|
+
state.hasReceivedDeltas = true;
|
|
1027
1201
|
}
|
|
1028
1202
|
const toolUseId = state.toolIdMapping.get(item.id);
|
|
1029
1203
|
if (!toolUseId) return;
|
|
@@ -1040,19 +1214,22 @@ ${this.args.appendSystemPrompt}`;
|
|
|
1040
1214
|
content: item.status === "failed" ? { is_error: true, error: item.error?.message || "Failed" } : content
|
|
1041
1215
|
});
|
|
1042
1216
|
}
|
|
1043
|
-
handleFileChange(item, state, currentMessageContent, pendingToolResults) {
|
|
1217
|
+
handleFileChange(item, state, currentMessageContent, pendingToolResults, model, currentMessageId) {
|
|
1044
1218
|
if (!state.emittedToolIds.has(item.id)) {
|
|
1045
1219
|
const toolUseId2 = generateToolUseId();
|
|
1046
1220
|
state.emittedToolIds.add(item.id);
|
|
1047
1221
|
state.toolIdMapping.set(item.id, toolUseId2);
|
|
1048
1222
|
const change2 = item.changes[0];
|
|
1049
1223
|
const toolName = change2.kind === "add" ? "Write" : "Edit";
|
|
1050
|
-
|
|
1224
|
+
const toolUse = {
|
|
1051
1225
|
type: "tool_use",
|
|
1052
1226
|
id: toolUseId2,
|
|
1053
1227
|
name: toolName,
|
|
1054
1228
|
input: { file_path: change2.path }
|
|
1055
|
-
}
|
|
1229
|
+
};
|
|
1230
|
+
currentMessageContent.push(toolUse);
|
|
1231
|
+
this.emitAssistantMessage(currentMessageId, model, [toolUse], void 0, null);
|
|
1232
|
+
state.hasReceivedDeltas = true;
|
|
1056
1233
|
}
|
|
1057
1234
|
const toolUseId = state.toolIdMapping.get(item.id);
|
|
1058
1235
|
if (!toolUseId) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hankweave",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Orchestration runtime for antibrittle agentic workflows",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Southbridge AI",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@ai-sdk/groq": "^2.0.11",
|
|
82
82
|
"@ai-sdk/openai": "^2.0.18",
|
|
83
83
|
"@anthropic-ai/claude-agent-sdk": "^0.1.70",
|
|
84
|
-
"@openai/codex-sdk": "^0.
|
|
84
|
+
"@openai/codex-sdk": "^0.98.0",
|
|
85
85
|
"ai": "^5.0.15",
|
|
86
86
|
"crossws": "^0.4.1",
|
|
87
87
|
"eta": "^3.5.0",
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
"ignore": "^7.0.5",
|
|
90
90
|
"lodash.merge": "^4.6.2",
|
|
91
91
|
"minimatch": "^10.0.1",
|
|
92
|
+
"posthog-node": "^5.24.10",
|
|
92
93
|
"simple-git": "^3.28.0",
|
|
93
94
|
"srvx": "^0.10.0",
|
|
94
95
|
"zod": "^3.25.74"
|
|
@@ -79,6 +79,26 @@
|
|
|
79
79
|
"additionalProperties": false,
|
|
80
80
|
"description": "Sentinel system configuration"
|
|
81
81
|
},
|
|
82
|
+
"telemetry": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"properties": {
|
|
85
|
+
"enabled": {
|
|
86
|
+
"type": "boolean",
|
|
87
|
+
"description": "Enable or disable telemetry"
|
|
88
|
+
},
|
|
89
|
+
"endpoint": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"format": "uri",
|
|
92
|
+
"description": "Custom telemetry endpoint URL"
|
|
93
|
+
},
|
|
94
|
+
"debug": {
|
|
95
|
+
"type": "boolean",
|
|
96
|
+
"description": "Print payloads to console instead of sending"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"description": "Telemetry configuration"
|
|
101
|
+
},
|
|
82
102
|
"$schema": {
|
|
83
103
|
"type": "string",
|
|
84
104
|
"description": "JSON Schema URL for editor support"
|