snipara-companion 3.3.0 → 3.4.1
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/CHANGELOG.md +16 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +197 -11
- package/docs/FULL_REFERENCE.md +28 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Release notes for `snipara-companion`, newest first.
|
|
4
4
|
|
|
5
|
+
## New In 3.4.1
|
|
6
|
+
|
|
7
|
+
- Declares provider API keys by environment-variable name and supports
|
|
8
|
+
`authorization` or `x-api-key` headers without persisting secret values.
|
|
9
|
+
- Resolves declared Codex and Claude CLI workers to explicit native adapters;
|
|
10
|
+
unsupported generic CLI profiles fail closed.
|
|
11
|
+
- Preserves opt-in local routing behavior while forwarding provider auth metadata
|
|
12
|
+
to the orchestrator catalog.
|
|
13
|
+
|
|
14
|
+
## New In 3.4.0
|
|
15
|
+
|
|
16
|
+
- Adds repeatable `workers execute --output-fragment` contracts.
|
|
17
|
+
- Fails a worker receipt closed when declared output fragments are missing,
|
|
18
|
+
while preserving explicit approval, proof, and Git scope gates.
|
|
19
|
+
- Persists missing output fragments in the receipt for review and calibration.
|
|
20
|
+
|
|
5
21
|
## New In 3.3.0
|
|
6
22
|
|
|
7
23
|
- Adds reviewed, scoped Worker Trust Promotion commands: `workers trust
|
package/dist/index.d.ts
CHANGED
|
@@ -4478,6 +4478,8 @@ interface LocalWorkerDeclaration {
|
|
|
4478
4478
|
endpointType: "local";
|
|
4479
4479
|
provider: string;
|
|
4480
4480
|
baseUrl: string;
|
|
4481
|
+
apiKeyEnv?: string;
|
|
4482
|
+
apiKeyHeader?: "authorization" | "x-api-key";
|
|
4481
4483
|
command?: string;
|
|
4482
4484
|
model?: string;
|
|
4483
4485
|
preferModel?: string;
|
|
@@ -4496,11 +4498,16 @@ interface LocalWorkersConfig {
|
|
|
4496
4498
|
interface LocalWorkerRoutingDefaults {
|
|
4497
4499
|
worker: LocalWorkerDeclaration;
|
|
4498
4500
|
routeLocalWorkers: true;
|
|
4501
|
+
routingLocalTransport: "openai_http" | "cli";
|
|
4502
|
+
routingLocalAdapter?: "codex_app_server" | "claude_cli";
|
|
4503
|
+
routingLocalCommand?: string;
|
|
4499
4504
|
routingWorkerRole: string;
|
|
4500
4505
|
routingLocalBaseUrl: string;
|
|
4501
4506
|
routingLocalModel?: string;
|
|
4502
4507
|
routingLocalPreferModel?: string;
|
|
4503
4508
|
routingLocalProvider: string;
|
|
4509
|
+
routingLocalApiKeyEnv?: string;
|
|
4510
|
+
routingLocalApiKeyHeader?: "authorization" | "x-api-key";
|
|
4504
4511
|
routingPreferredEndpoints: string[];
|
|
4505
4512
|
routingAllowedEndpoints: string[];
|
|
4506
4513
|
plannerRetainsReasoning: true;
|
|
@@ -4520,6 +4527,8 @@ interface LocalWorkerAddOptions {
|
|
|
4520
4527
|
json?: boolean;
|
|
4521
4528
|
transport?: "openai_http" | "cli";
|
|
4522
4529
|
command?: string;
|
|
4530
|
+
apiKeyEnv?: string;
|
|
4531
|
+
apiKeyHeader?: "authorization" | "x-api-key";
|
|
4523
4532
|
}
|
|
4524
4533
|
interface LocalWorkerStatusOptions {
|
|
4525
4534
|
json?: boolean;
|
|
@@ -4542,6 +4551,8 @@ interface LocalWorkerProbeOptions {
|
|
|
4542
4551
|
writeScope?: string[];
|
|
4543
4552
|
reasoning?: "low" | "medium" | "high";
|
|
4544
4553
|
contextWindow?: number;
|
|
4554
|
+
apiKeyEnv?: string;
|
|
4555
|
+
apiKeyHeader?: "authorization" | "x-api-key";
|
|
4545
4556
|
json?: boolean;
|
|
4546
4557
|
}
|
|
4547
4558
|
declare function workersLocalAddCommand(options: LocalWorkerAddOptions): void;
|
|
@@ -4575,6 +4586,7 @@ interface ControlledWorkerExecuteOptions {
|
|
|
4575
4586
|
writeScope?: string[];
|
|
4576
4587
|
acceptance?: string[];
|
|
4577
4588
|
proof?: string[];
|
|
4589
|
+
outputFragments?: string[];
|
|
4578
4590
|
workCategory?: WorkerTrustCategory;
|
|
4579
4591
|
trustEvent?: string;
|
|
4580
4592
|
profileHash?: string;
|
package/dist/index.js
CHANGED
|
@@ -9755,7 +9755,9 @@ function normalizeWorkerProfileTransport(value) {
|
|
|
9755
9755
|
baseUrl,
|
|
9756
9756
|
...stringValue(value.model) ? { model: stringValue(value.model) } : {},
|
|
9757
9757
|
...stringValue(value.preferModel) ? { preferModel: stringValue(value.preferModel) } : {},
|
|
9758
|
-
...stringValue(value.provider) ? { provider: stringValue(value.provider) } : {}
|
|
9758
|
+
...stringValue(value.provider) ? { provider: stringValue(value.provider) } : {},
|
|
9759
|
+
...safeEnvironmentVariableName(value.apiKeyEnv) ? { apiKeyEnv: safeEnvironmentVariableName(value.apiKeyEnv) } : {},
|
|
9760
|
+
...value.apiKeyHeader === "authorization" || value.apiKeyHeader === "x-api-key" ? { apiKeyHeader: value.apiKeyHeader } : {}
|
|
9759
9761
|
};
|
|
9760
9762
|
}
|
|
9761
9763
|
if (kind === "cli") {
|
|
@@ -9897,6 +9899,10 @@ function numberValue(value) {
|
|
|
9897
9899
|
function booleanValue(value) {
|
|
9898
9900
|
return value === true;
|
|
9899
9901
|
}
|
|
9902
|
+
function safeEnvironmentVariableName(value) {
|
|
9903
|
+
const normalized = stringValue(value);
|
|
9904
|
+
return normalized && /^[A-Za-z_][A-Za-z0-9_]*$/.test(normalized) ? normalized : void 0;
|
|
9905
|
+
}
|
|
9900
9906
|
function stringValue(value) {
|
|
9901
9907
|
if (value === null || value === void 0) {
|
|
9902
9908
|
return void 0;
|
|
@@ -11247,6 +11253,8 @@ function buildControlledWorkerExecutionReceipt(input) {
|
|
|
11247
11253
|
const writeScope = uniqueStrings9(input.writeScope ?? []);
|
|
11248
11254
|
const acceptanceCriteria = uniqueStrings9(input.acceptanceCriteria ?? []);
|
|
11249
11255
|
const proofRequired = uniqueStrings9(input.proofRequired ?? []);
|
|
11256
|
+
const outputFragments = uniqueStrings9(input.outputFragments ?? []);
|
|
11257
|
+
const missingOutputFragments = uniqueStrings9(input.missingOutputFragments ?? []);
|
|
11250
11258
|
const reasonCodes = /* @__PURE__ */ new Set([
|
|
11251
11259
|
"controlled_worker_execution_v0",
|
|
11252
11260
|
`controlled_worker_execution_${mode}`,
|
|
@@ -11266,6 +11274,8 @@ function buildControlledWorkerExecutionReceipt(input) {
|
|
|
11266
11274
|
writeScope,
|
|
11267
11275
|
acceptanceCriteria,
|
|
11268
11276
|
proofRequired,
|
|
11277
|
+
outputFragments,
|
|
11278
|
+
missingOutputFragments,
|
|
11269
11279
|
approvalReceiptId: input.approvalReceiptId ?? null,
|
|
11270
11280
|
outcomeReceiptId: input.outcomeReceiptId ?? null,
|
|
11271
11281
|
command,
|
|
@@ -11282,6 +11292,9 @@ function buildControlledWorkerExecutionReceipt(input) {
|
|
|
11282
11292
|
if (acceptanceCriteria.length === 0) {
|
|
11283
11293
|
reasonCodes.add("controlled_worker_execution_missing_acceptance");
|
|
11284
11294
|
}
|
|
11295
|
+
if (missingOutputFragments.length > 0) {
|
|
11296
|
+
reasonCodes.add("controlled_worker_execution_output_contract_failed");
|
|
11297
|
+
}
|
|
11285
11298
|
return {
|
|
11286
11299
|
version: CONTROLLED_WORKER_EXECUTION_RECEIPT_VERSION,
|
|
11287
11300
|
receiptId: `worker-exec-${receiptHash.slice(0, 16)}`,
|
|
@@ -11294,6 +11307,8 @@ function buildControlledWorkerExecutionReceipt(input) {
|
|
|
11294
11307
|
writeScope,
|
|
11295
11308
|
acceptanceCriteria,
|
|
11296
11309
|
proofRequired,
|
|
11310
|
+
outputFragments,
|
|
11311
|
+
missingOutputFragments,
|
|
11297
11312
|
approvalReceiptId: input.approvalReceiptId ?? null,
|
|
11298
11313
|
outcomeReceiptId: input.outcomeReceiptId ?? null
|
|
11299
11314
|
},
|
|
@@ -19618,6 +19633,9 @@ function workersLocalAddCommand(options) {
|
|
|
19618
19633
|
printKeyValue("Role:", result.worker.workerRole);
|
|
19619
19634
|
printKeyValue("Provider:", result.worker.provider);
|
|
19620
19635
|
printKeyValue("Base URL:", result.worker.baseUrl);
|
|
19636
|
+
if (result.worker.apiKeyEnv) {
|
|
19637
|
+
printKeyValue("API key env:", result.worker.apiKeyEnv);
|
|
19638
|
+
}
|
|
19621
19639
|
if (result.worker.model) {
|
|
19622
19640
|
printKeyValue("Model:", result.worker.model);
|
|
19623
19641
|
} else if (result.worker.preferModel) {
|
|
@@ -19709,7 +19727,9 @@ function workersLocalProbeCommand(options) {
|
|
|
19709
19727
|
capabilities: normalizeStringList3(options.capabilities),
|
|
19710
19728
|
writeScope: normalizeStringList3(options.writeScope),
|
|
19711
19729
|
model,
|
|
19712
|
-
preferModel
|
|
19730
|
+
preferModel,
|
|
19731
|
+
apiKeyEnv: options.apiKeyEnv,
|
|
19732
|
+
apiKeyHeader: options.apiKeyHeader
|
|
19713
19733
|
});
|
|
19714
19734
|
const catalogContextWindow = resolveContextWindowFromCatalog(catalog, model, preferModel);
|
|
19715
19735
|
const contextWindow = normalizeContextWindow(
|
|
@@ -19728,7 +19748,9 @@ function workersLocalProbeCommand(options) {
|
|
|
19728
19748
|
baseUrl,
|
|
19729
19749
|
...model ? { model } : {},
|
|
19730
19750
|
...preferModel ? { preferModel } : {},
|
|
19731
|
-
provider
|
|
19751
|
+
provider,
|
|
19752
|
+
...options.apiKeyEnv ? { apiKeyEnv: options.apiKeyEnv } : {},
|
|
19753
|
+
...options.apiKeyHeader ? { apiKeyHeader: options.apiKeyHeader } : {}
|
|
19732
19754
|
},
|
|
19733
19755
|
capabilities: {
|
|
19734
19756
|
roles: [role],
|
|
@@ -19882,7 +19904,26 @@ function resolveLocalWorkerRoutingDefaults(options = {}) {
|
|
|
19882
19904
|
throw new Error(`Local worker ${requestedId} is not declared.`);
|
|
19883
19905
|
}
|
|
19884
19906
|
if (!worker.baseUrl || worker.baseUrl === "cli://command") {
|
|
19885
|
-
|
|
19907
|
+
const command = worker.command?.toLowerCase() ?? "";
|
|
19908
|
+
const adapter = command.includes("codex") ? "codex_app_server" : command.includes("claude") ? "claude_cli" : void 0;
|
|
19909
|
+
if (!adapter) {
|
|
19910
|
+
throw new Error(
|
|
19911
|
+
`CLI worker ${worker.id} is not mapped to a supported native adapter; use a Codex or Claude command.`
|
|
19912
|
+
);
|
|
19913
|
+
}
|
|
19914
|
+
return {
|
|
19915
|
+
worker,
|
|
19916
|
+
routeLocalWorkers: true,
|
|
19917
|
+
routingLocalTransport: "cli",
|
|
19918
|
+
routingLocalBaseUrl: "cli://command",
|
|
19919
|
+
routingLocalAdapter: adapter,
|
|
19920
|
+
routingLocalCommand: worker.command,
|
|
19921
|
+
routingWorkerRole: worker.workerRole,
|
|
19922
|
+
routingLocalProvider: worker.provider,
|
|
19923
|
+
routingPreferredEndpoints: ["local"],
|
|
19924
|
+
routingAllowedEndpoints: ["local"],
|
|
19925
|
+
plannerRetainsReasoning: true
|
|
19926
|
+
};
|
|
19886
19927
|
}
|
|
19887
19928
|
if (!worker.model && !worker.preferModel) {
|
|
19888
19929
|
const hasCatalogHint = true;
|
|
@@ -19891,11 +19932,14 @@ function resolveLocalWorkerRoutingDefaults(options = {}) {
|
|
|
19891
19932
|
return {
|
|
19892
19933
|
worker,
|
|
19893
19934
|
routeLocalWorkers: true,
|
|
19935
|
+
routingLocalTransport: "openai_http",
|
|
19894
19936
|
routingWorkerRole: worker.workerRole,
|
|
19895
19937
|
routingLocalBaseUrl: worker.baseUrl,
|
|
19896
19938
|
...worker.model ? { routingLocalModel: worker.model } : {},
|
|
19897
19939
|
...worker.preferModel ? { routingLocalPreferModel: worker.preferModel } : {},
|
|
19898
19940
|
routingLocalProvider: worker.provider,
|
|
19941
|
+
...worker.apiKeyEnv ? { routingLocalApiKeyEnv: worker.apiKeyEnv } : {},
|
|
19942
|
+
...worker.apiKeyHeader ? { routingLocalApiKeyHeader: worker.apiKeyHeader } : {},
|
|
19899
19943
|
routingPreferredEndpoints: ["local"],
|
|
19900
19944
|
routingAllowedEndpoints: ["local"],
|
|
19901
19945
|
plannerRetainsReasoning: true
|
|
@@ -20003,7 +20047,9 @@ function normalizeWorkerProfileRecord(value) {
|
|
|
20003
20047
|
transport: {
|
|
20004
20048
|
...transport,
|
|
20005
20049
|
baseUrl,
|
|
20006
|
-
provider: normalizeProvider(transport.provider ?? "lm-studio")
|
|
20050
|
+
provider: normalizeProvider(transport.provider ?? "lm-studio"),
|
|
20051
|
+
...transport.apiKeyEnv ? { apiKeyEnv: transport.apiKeyEnv } : {},
|
|
20052
|
+
...transport.apiKeyHeader ? { apiKeyHeader: transport.apiKeyHeader } : {}
|
|
20007
20053
|
}
|
|
20008
20054
|
};
|
|
20009
20055
|
}
|
|
@@ -20038,7 +20084,9 @@ function toProfileFromLegacyWorker(worker) {
|
|
|
20038
20084
|
baseUrl: worker.baseUrl,
|
|
20039
20085
|
...worker.model ? { model: worker.model } : {},
|
|
20040
20086
|
...worker.preferModel ? { preferModel: worker.preferModel } : {},
|
|
20041
|
-
provider: worker.provider
|
|
20087
|
+
provider: worker.provider,
|
|
20088
|
+
...worker.apiKeyEnv ? { apiKeyEnv: worker.apiKeyEnv } : {},
|
|
20089
|
+
...worker.apiKeyHeader ? { apiKeyHeader: worker.apiKeyHeader } : {}
|
|
20042
20090
|
},
|
|
20043
20091
|
capabilities: {
|
|
20044
20092
|
roles: [normalizeWorkerRole(worker.workerRole)],
|
|
@@ -20081,6 +20129,8 @@ function toLocalWorkerDeclaration(profile) {
|
|
|
20081
20129
|
endpointType: "local",
|
|
20082
20130
|
provider: normalizeProvider(profile.transport.provider ?? "lm-studio"),
|
|
20083
20131
|
baseUrl: profile.transport.baseUrl,
|
|
20132
|
+
...profile.transport.apiKeyEnv ? { apiKeyEnv: profile.transport.apiKeyEnv } : {},
|
|
20133
|
+
...profile.transport.apiKeyHeader ? { apiKeyHeader: profile.transport.apiKeyHeader } : {},
|
|
20084
20134
|
...stringValue6(profile.transport.model) ? { model: stringValue6(profile.transport.model) } : {},
|
|
20085
20135
|
...stringValue6(profile.transport.preferModel) && !profile.transport.model ? { preferModel: stringValue6(profile.transport.preferModel) } : {},
|
|
20086
20136
|
capabilities: normalizeWorkerCapabilities(profile.capabilities.roles),
|
|
@@ -20186,6 +20236,12 @@ function runOrchestratorLocalCatalog(options) {
|
|
|
20186
20236
|
if (options.preferModel) {
|
|
20187
20237
|
args.push("--prefer-model", options.preferModel);
|
|
20188
20238
|
}
|
|
20239
|
+
if (options.apiKeyEnv) {
|
|
20240
|
+
args.push("--api-key-env", options.apiKeyEnv);
|
|
20241
|
+
}
|
|
20242
|
+
if (options.apiKeyHeader) {
|
|
20243
|
+
args.push("--api-key-header", options.apiKeyHeader);
|
|
20244
|
+
}
|
|
20189
20245
|
try {
|
|
20190
20246
|
const result = (0, import_node_child_process9.execFileSync)("snipara-orchestrator", args, {
|
|
20191
20247
|
encoding: "utf8",
|
|
@@ -20321,12 +20377,15 @@ function normalizeWorkerTransport(options) {
|
|
|
20321
20377
|
const baseUrl = normalizeBaseUrl(options.baseUrl ?? "http://127.0.0.1:1234");
|
|
20322
20378
|
const model = stringValue6(options.model);
|
|
20323
20379
|
const preferModel = stringValue6(options.preferModel);
|
|
20380
|
+
const apiKeyEnv = normalizeApiKeyEnvironmentName(options.apiKeyEnv);
|
|
20324
20381
|
return {
|
|
20325
20382
|
kind: "openai_http",
|
|
20326
20383
|
baseUrl,
|
|
20327
20384
|
...model ? { model } : {},
|
|
20328
20385
|
...preferModel ? { preferModel } : {},
|
|
20329
|
-
provider: normalizeProvider(stringValue6(options.provider) ?? "lm-studio")
|
|
20386
|
+
provider: normalizeProvider(stringValue6(options.provider) ?? "lm-studio"),
|
|
20387
|
+
...apiKeyEnv ? { apiKeyEnv } : {},
|
|
20388
|
+
...options.apiKeyHeader ? { apiKeyHeader: options.apiKeyHeader } : {}
|
|
20330
20389
|
};
|
|
20331
20390
|
}
|
|
20332
20391
|
function normalizeProvider(value) {
|
|
@@ -20348,6 +20407,8 @@ function normalizeLegacyWorkerDeclaration(value) {
|
|
|
20348
20407
|
endpointType: "local",
|
|
20349
20408
|
provider: normalizeProvider(stringValue6(value.provider) ?? "lm-studio"),
|
|
20350
20409
|
baseUrl,
|
|
20410
|
+
...stringValue6(value.apiKeyEnv) ? { apiKeyEnv: stringValue6(value.apiKeyEnv) } : {},
|
|
20411
|
+
...value.apiKeyHeader === "authorization" || value.apiKeyHeader === "x-api-key" ? { apiKeyHeader: value.apiKeyHeader } : {},
|
|
20351
20412
|
...stringValue6(value.model) ? { model: stringValue6(value.model) } : {},
|
|
20352
20413
|
...stringValue6(value.preferModel) ? { preferModel: stringValue6(value.preferModel) } : {},
|
|
20353
20414
|
capabilities: normalizeStringList3(value.capabilities).length > 0 ? normalizeStringList3(value.capabilities) : defaultCapabilitiesForWorker(normalizeWorkerRole(value.workerRole)),
|
|
@@ -20425,6 +20486,16 @@ function stringValue6(value) {
|
|
|
20425
20486
|
const stringified = String(value).trim();
|
|
20426
20487
|
return stringified || void 0;
|
|
20427
20488
|
}
|
|
20489
|
+
function normalizeApiKeyEnvironmentName(value) {
|
|
20490
|
+
const normalized = stringValue6(value);
|
|
20491
|
+
if (!normalized) {
|
|
20492
|
+
return void 0;
|
|
20493
|
+
}
|
|
20494
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(normalized)) {
|
|
20495
|
+
throw new Error("API key env must be a shell-safe environment variable name.");
|
|
20496
|
+
}
|
|
20497
|
+
return normalized;
|
|
20498
|
+
}
|
|
20428
20499
|
function isRecord10(value) {
|
|
20429
20500
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20430
20501
|
}
|
|
@@ -25416,7 +25487,7 @@ function shouldResolveAdaptiveRoutingLocally(options, routing) {
|
|
|
25416
25487
|
return preferred.includes("local") || allowed.length === 0 || allowed.includes("local");
|
|
25417
25488
|
}
|
|
25418
25489
|
function hasLocalRoutingRequest(options) {
|
|
25419
|
-
return options.routeLocalWorkers === true || Boolean(options.routingLocalWorker) || Boolean(options.routingLocalBaseUrl) || Boolean(options.routingLocalModel) || Boolean(options.routingLocalPreferModel) || Boolean(options.routingLocalProvider) || normalizeRoutingEndpointTypes(options.routingPreferredEndpoints).includes("local") || normalizeRoutingEndpointTypes(options.routingAllowedEndpoints).includes("local");
|
|
25490
|
+
return options.routeLocalWorkers === true || Boolean(options.routingLocalWorker) || Boolean(options.routingLocalBaseUrl) || Boolean(options.routingLocalModel) || Boolean(options.routingLocalPreferModel) || Boolean(options.routingLocalProvider) || Boolean(options.routingLocalApiKeyEnv) || normalizeRoutingEndpointTypes(options.routingPreferredEndpoints).includes("local") || normalizeRoutingEndpointTypes(options.routingAllowedEndpoints).includes("local");
|
|
25420
25491
|
}
|
|
25421
25492
|
function applyLocalWorkerRoutingDefaults(options, defaults) {
|
|
25422
25493
|
if (!defaults) {
|
|
@@ -25425,6 +25496,9 @@ function applyLocalWorkerRoutingDefaults(options, defaults) {
|
|
|
25425
25496
|
return {
|
|
25426
25497
|
...options,
|
|
25427
25498
|
routeLocalWorkers: options.routeLocalWorkers ?? defaults.routeLocalWorkers,
|
|
25499
|
+
routingLocalTransport: options.routingLocalTransport ?? defaults.routingLocalTransport,
|
|
25500
|
+
routingLocalAdapter: options.routingLocalAdapter ?? defaults.routingLocalAdapter,
|
|
25501
|
+
routingLocalCommand: options.routingLocalCommand ?? defaults.routingLocalCommand,
|
|
25428
25502
|
routingWorkerRole: options.routingWorkerRole ?? defaults.routingWorkerRole,
|
|
25429
25503
|
routingPreferredEndpoints: options.routingPreferredEndpoints && options.routingPreferredEndpoints.length > 0 ? options.routingPreferredEndpoints : defaults.routingPreferredEndpoints,
|
|
25430
25504
|
routingAllowedEndpoints: options.routingAllowedEndpoints && options.routingAllowedEndpoints.length > 0 ? options.routingAllowedEndpoints : defaults.routingAllowedEndpoints,
|
|
@@ -25432,6 +25506,8 @@ function applyLocalWorkerRoutingDefaults(options, defaults) {
|
|
|
25432
25506
|
routingLocalModel: options.routingLocalModel ?? defaults.routingLocalModel,
|
|
25433
25507
|
routingLocalPreferModel: options.routingLocalPreferModel ?? defaults.routingLocalPreferModel,
|
|
25434
25508
|
routingLocalProvider: options.routingLocalProvider ?? defaults.routingLocalProvider,
|
|
25509
|
+
routingLocalApiKeyEnv: options.routingLocalApiKeyEnv ?? defaults.routingLocalApiKeyEnv,
|
|
25510
|
+
routingLocalApiKeyHeader: options.routingLocalApiKeyHeader ?? defaults.routingLocalApiKeyHeader,
|
|
25435
25511
|
plannerRetainsReasoning: options.plannerRetainsReasoning ?? defaults.plannerRetainsReasoning
|
|
25436
25512
|
};
|
|
25437
25513
|
}
|
|
@@ -25446,6 +25522,67 @@ function runOrchestratorJsonCommand(args, cwd = process.cwd()) {
|
|
|
25446
25522
|
}
|
|
25447
25523
|
function enrichAdaptiveRoutingWithLocalOrchestrator(routing, options, cwd = process.cwd()) {
|
|
25448
25524
|
try {
|
|
25525
|
+
if (options.routingLocalTransport === "cli") {
|
|
25526
|
+
const candidateId = options.routingLocalAdapter ?? options.routingLocalCommand ?? "declared-cli";
|
|
25527
|
+
const candidate = {
|
|
25528
|
+
candidateId,
|
|
25529
|
+
workerClass: routing.requirements.workerRole,
|
|
25530
|
+
catalogSource: "declared_cli_worker",
|
|
25531
|
+
endpointType: "local",
|
|
25532
|
+
workerRoles: [routing.requirements.workerRole],
|
|
25533
|
+
capabilities: routing.requirements.capabilities ?? [],
|
|
25534
|
+
writeScope: routing.requirements.writeScope ?? [],
|
|
25535
|
+
reasoning: routing.requirements.reasoning,
|
|
25536
|
+
speed: "normal",
|
|
25537
|
+
cost: "balanced",
|
|
25538
|
+
contextBudget: routing.requirements.contextBudget,
|
|
25539
|
+
qualityScore: null,
|
|
25540
|
+
isAvailable: true,
|
|
25541
|
+
requiresApiKey: false,
|
|
25542
|
+
metadata: {
|
|
25543
|
+
adapter: options.routingLocalAdapter,
|
|
25544
|
+
command: options.routingLocalCommand
|
|
25545
|
+
}
|
|
25546
|
+
};
|
|
25547
|
+
const resolution2 = normalizeAdaptiveRoutingResolution(
|
|
25548
|
+
runOrchestratorJsonCommand(
|
|
25549
|
+
[
|
|
25550
|
+
"route",
|
|
25551
|
+
"--dry-run",
|
|
25552
|
+
"--json",
|
|
25553
|
+
"--work-profile-json",
|
|
25554
|
+
JSON.stringify(routing.workProfile),
|
|
25555
|
+
"--requirements-json",
|
|
25556
|
+
JSON.stringify(routing.requirements),
|
|
25557
|
+
"--candidate-json",
|
|
25558
|
+
JSON.stringify(candidate)
|
|
25559
|
+
],
|
|
25560
|
+
cwd
|
|
25561
|
+
)
|
|
25562
|
+
);
|
|
25563
|
+
return {
|
|
25564
|
+
...routing,
|
|
25565
|
+
gateway: {
|
|
25566
|
+
source: "local_orchestrator",
|
|
25567
|
+
success: true,
|
|
25568
|
+
resolutionStatus: resolution2?.status ?? "resolved",
|
|
25569
|
+
candidateCount: 1,
|
|
25570
|
+
fallback: "main_agent",
|
|
25571
|
+
warnings: []
|
|
25572
|
+
},
|
|
25573
|
+
runtimeCatalog: {
|
|
25574
|
+
source: "declared_cli_worker",
|
|
25575
|
+
candidates: [candidate],
|
|
25576
|
+
workerEndpoints: {
|
|
25577
|
+
[candidateId]: {
|
|
25578
|
+
adapter: options.routingLocalAdapter,
|
|
25579
|
+
command: options.routingLocalCommand
|
|
25580
|
+
}
|
|
25581
|
+
}
|
|
25582
|
+
},
|
|
25583
|
+
resolution: resolution2
|
|
25584
|
+
};
|
|
25585
|
+
}
|
|
25449
25586
|
const catalogArgs = [
|
|
25450
25587
|
"local-model-catalog",
|
|
25451
25588
|
"--json",
|
|
@@ -25468,6 +25605,12 @@ function enrichAdaptiveRoutingWithLocalOrchestrator(routing, options, cwd = proc
|
|
|
25468
25605
|
if (options.routingLocalProvider) {
|
|
25469
25606
|
catalogArgs.push("--provider", options.routingLocalProvider);
|
|
25470
25607
|
}
|
|
25608
|
+
if (options.routingLocalApiKeyEnv) {
|
|
25609
|
+
catalogArgs.push("--api-key-env", options.routingLocalApiKeyEnv);
|
|
25610
|
+
}
|
|
25611
|
+
if (options.routingLocalApiKeyHeader) {
|
|
25612
|
+
catalogArgs.push("--api-key-header", options.routingLocalApiKeyHeader);
|
|
25613
|
+
}
|
|
25471
25614
|
const runtimeCatalog = normalizeAdaptiveRoutingCatalog(
|
|
25472
25615
|
runOrchestratorJsonCommand(catalogArgs, cwd)
|
|
25473
25616
|
);
|
|
@@ -27358,7 +27501,7 @@ async function workflowRunCommand(options) {
|
|
|
27358
27501
|
}
|
|
27359
27502
|
function shouldBuildAdaptiveRouting(options) {
|
|
27360
27503
|
return Boolean(
|
|
27361
|
-
options.adaptiveRoutingDryRun || options.routeLocalWorkers || options.routingLocalWorker || options.routingWorkerRole || options.routingPreferredEndpoints?.length || options.routingAllowedEndpoints?.length || options.routingLocalBaseUrl || options.routingLocalModel || options.routingLocalPreferModel || options.routingLocalProvider || options.plannerRetainsReasoning
|
|
27504
|
+
options.adaptiveRoutingDryRun || options.routeLocalWorkers || options.routingLocalWorker || options.routingWorkerRole || options.routingPreferredEndpoints?.length || options.routingAllowedEndpoints?.length || options.routingLocalBaseUrl || options.routingLocalModel || options.routingLocalPreferModel || options.routingLocalProvider || options.routingLocalApiKeyEnv || options.plannerRetainsReasoning
|
|
27362
27505
|
);
|
|
27363
27506
|
}
|
|
27364
27507
|
function buildWorkflowAdaptiveRouting(options, policy = null, intentWarnings = []) {
|
|
@@ -29914,6 +30057,7 @@ function controlledWorkerExecuteCommand(options) {
|
|
|
29914
30057
|
const execute = Boolean(options.execute);
|
|
29915
30058
|
const mode = normalizeMode(options.mode, execute);
|
|
29916
30059
|
const commandArgs = normalizeCommandArgs(options.commandArgs);
|
|
30060
|
+
const outputFragments = normalizeOutputFragments(options.outputFragments);
|
|
29917
30061
|
const legacyCommand = stringValue8(options.command);
|
|
29918
30062
|
const command = commandArgs.length > 0 ? commandArgs.join(" ") : legacyCommand;
|
|
29919
30063
|
const risk = command ? commandRisk(command) : "none";
|
|
@@ -29959,6 +30103,7 @@ function controlledWorkerExecuteCommand(options) {
|
|
|
29959
30103
|
let executionAttempted = false;
|
|
29960
30104
|
let changedFiles = [];
|
|
29961
30105
|
let scopeViolations = [];
|
|
30106
|
+
let missingOutputFragments = [];
|
|
29962
30107
|
if (execute) reasonCodes.add("controlled_worker_execution_requested");
|
|
29963
30108
|
if (!execute) reasonCodes.add("controlled_worker_execution_dry_run_only");
|
|
29964
30109
|
if (missingApproval) reasonCodes.add("controlled_worker_execution_missing_approval");
|
|
@@ -29996,6 +30141,13 @@ function controlledWorkerExecuteCommand(options) {
|
|
|
29996
30141
|
exitCode = typeof result2.status === "number" ? result2.status : 1;
|
|
29997
30142
|
stdout = result2.stdout ?? "";
|
|
29998
30143
|
stderr = result2.stderr ?? "";
|
|
30144
|
+
missingOutputFragments = outputFragments.filter(
|
|
30145
|
+
(fragment) => !normalizeComparableText(stdout).includes(normalizeComparableText(fragment))
|
|
30146
|
+
);
|
|
30147
|
+
if (missingOutputFragments.length > 0) {
|
|
30148
|
+
blocked = true;
|
|
30149
|
+
reasonCodes.add("controlled_worker_execution_output_contract_failed");
|
|
30150
|
+
}
|
|
29999
30151
|
reasonCodes.add(
|
|
30000
30152
|
exitCode === 0 ? "controlled_worker_execution_command_succeeded" : "controlled_worker_execution_command_failed"
|
|
30001
30153
|
);
|
|
@@ -30030,6 +30182,8 @@ function controlledWorkerExecuteCommand(options) {
|
|
|
30030
30182
|
writeScope: options.writeScope,
|
|
30031
30183
|
acceptanceCriteria: options.acceptance,
|
|
30032
30184
|
proofRequired: options.proof,
|
|
30185
|
+
outputFragments,
|
|
30186
|
+
missingOutputFragments,
|
|
30033
30187
|
approvalReceiptId: options.approvalReceipt ?? null,
|
|
30034
30188
|
outcomeReceiptId: options.outcomeReceipt ?? null,
|
|
30035
30189
|
command: command ?? null,
|
|
@@ -30100,6 +30254,12 @@ function controlledWorkerExecuteCommand(options) {
|
|
|
30100
30254
|
function normalizeCommandArgs(values) {
|
|
30101
30255
|
return (values ?? []).map((value) => value.trim()).filter(Boolean);
|
|
30102
30256
|
}
|
|
30257
|
+
function normalizeOutputFragments(values) {
|
|
30258
|
+
return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))].slice(0, 32);
|
|
30259
|
+
}
|
|
30260
|
+
function normalizeComparableText(value) {
|
|
30261
|
+
return value.toLowerCase().replace(/\s+/g, "");
|
|
30262
|
+
}
|
|
30103
30263
|
function gitScopeSnapshot(workspaceRoot2) {
|
|
30104
30264
|
const status = (0, import_node_child_process12.spawnSync)("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
|
|
30105
30265
|
cwd: workspaceRoot2,
|
|
@@ -38791,6 +38951,12 @@ workflow.command("run").description("Run a LITE/STANDARD/FULL/orchestrate workfl
|
|
|
38791
38951
|
"--routing-local-prefer-model <text>",
|
|
38792
38952
|
"Prefer a local /v1/models entry containing this text during worker routing"
|
|
38793
38953
|
).option("--routing-local-provider <provider>", "Provider label for local worker routing").option(
|
|
38954
|
+
"--routing-local-api-key-env <env>",
|
|
38955
|
+
"Environment variable containing the local/remote provider API key"
|
|
38956
|
+
).option(
|
|
38957
|
+
"--routing-local-api-key-header <header>",
|
|
38958
|
+
"Provider API key header: authorization or x-api-key"
|
|
38959
|
+
).option(
|
|
38794
38960
|
"--planner-retains-reasoning",
|
|
38795
38961
|
"Mark the main planner as retaining deep reasoning while the worker executes scoped work"
|
|
38796
38962
|
).option("--write-plan-file <file>", "Write the generated FULL-mode plan as workflow JSON").option(
|
|
@@ -38818,6 +38984,8 @@ workflow.command("run").description("Run a LITE/STANDARD/FULL/orchestrate workfl
|
|
|
38818
38984
|
routingLocalModel: options.routingLocalModel,
|
|
38819
38985
|
routingLocalPreferModel: options.routingLocalPreferModel,
|
|
38820
38986
|
routingLocalProvider: options.routingLocalProvider,
|
|
38987
|
+
routingLocalApiKeyEnv: options.routingLocalApiKeyEnv,
|
|
38988
|
+
routingLocalApiKeyHeader: options.routingLocalApiKeyHeader,
|
|
38821
38989
|
plannerRetainsReasoning: options.plannerRetainsReasoning ? true : void 0,
|
|
38822
38990
|
writePlanFile: options.writePlanFile,
|
|
38823
38991
|
startWorkflowFromPlan: Boolean(options.startWorkflowFromPlan),
|
|
@@ -38841,6 +39009,11 @@ workers.command("execute").description("Create a policy-gated Controlled Worker
|
|
|
38841
39009
|
"Required proof or verification command; repeatable",
|
|
38842
39010
|
collectOption,
|
|
38843
39011
|
[]
|
|
39012
|
+
).option(
|
|
39013
|
+
"--output-fragment <fragment>",
|
|
39014
|
+
"Required output fragment; repeatable and checked after execution",
|
|
39015
|
+
collectOption,
|
|
39016
|
+
[]
|
|
38844
39017
|
).option(
|
|
38845
39018
|
"--work-category <category>",
|
|
38846
39019
|
"Trust category; conservative task and scope signals can only escalate it"
|
|
@@ -38862,6 +39035,7 @@ workers.command("execute").description("Create a policy-gated Controlled Worker
|
|
|
38862
39035
|
writeScope: options.writeScope,
|
|
38863
39036
|
acceptance: options.acceptance,
|
|
38864
39037
|
proof: options.proof,
|
|
39038
|
+
outputFragments: options.outputFragment,
|
|
38865
39039
|
workCategory: options.workCategory,
|
|
38866
39040
|
trustEvent: options.trustEvent,
|
|
38867
39041
|
profileHash: options.profileHash,
|
|
@@ -38912,7 +39086,11 @@ localWorkers.command("add").description("Declare a local worker and enable local
|
|
|
38912
39086
|
"--role <role>",
|
|
38913
39087
|
"Worker role, for example coding, documentation, tests, or review",
|
|
38914
39088
|
"coding"
|
|
38915
|
-
).option("--provider <provider>", "Provider label", "lm-studio").option("--base-url <url>", "OpenAI-compatible local runtime base URL", "http://127.0.0.1:1234").option("--
|
|
39089
|
+
).option("--provider <provider>", "Provider label", "lm-studio").option("--base-url <url>", "OpenAI-compatible local runtime base URL", "http://127.0.0.1:1234").option("--api-key-env <env>", "Environment variable containing the provider API key").option(
|
|
39090
|
+
"--api-key-header <header>",
|
|
39091
|
+
"Provider API key header: authorization or x-api-key",
|
|
39092
|
+
"authorization"
|
|
39093
|
+
).option("--model <id>", "Exact model id exposed by the local runtime").option(
|
|
38916
39094
|
"--prefer-model <text>",
|
|
38917
39095
|
"Fallback model id substring to prefer when no exact model is set"
|
|
38918
39096
|
).option("--transport <openai_http|cli>", "Worker transport: openai_http (default) or cli").option("--command <command>", "CLI command to execute when transport is cli").option("--capability <capability>", "Worker capability; repeatable", collectOption, []).option(
|
|
@@ -38939,6 +39117,8 @@ localWorkers.command("add").description("Declare a local worker and enable local
|
|
|
38939
39117
|
preferModel: options.preferModel,
|
|
38940
39118
|
transport: options.transport,
|
|
38941
39119
|
command: options.command,
|
|
39120
|
+
apiKeyEnv: options.apiKeyEnv,
|
|
39121
|
+
apiKeyHeader: options.apiKeyHeader,
|
|
38942
39122
|
capabilities: options.capability,
|
|
38943
39123
|
reasoning: options.reasoning ? options.reasoning.toLowerCase() : void 0,
|
|
38944
39124
|
contextWindow: options.contextWindow,
|
|
@@ -38956,7 +39136,11 @@ localWorkers.command("list").description("List declared local workers").option("
|
|
|
38956
39136
|
localWorkers.command("remove").description("Remove a declared local worker").argument("id", "Local worker id").option("--json", "Print raw JSON").action((id, options) => {
|
|
38957
39137
|
workersLocalRemoveCommand({ id, json: options.json });
|
|
38958
39138
|
});
|
|
38959
|
-
localWorkers.command("probe").description("Probe an OpenAI-compatible endpoint and draft a worker suggestion").option("--base-url <url>", "OpenAI-compatible local runtime base URL", "http://127.0.0.1:1234").option("--
|
|
39139
|
+
localWorkers.command("probe").description("Probe an OpenAI-compatible endpoint and draft a worker suggestion").option("--base-url <url>", "OpenAI-compatible local runtime base URL", "http://127.0.0.1:1234").option("--api-key-env <env>", "Environment variable containing the provider API key").option(
|
|
39140
|
+
"--api-key-header <header>",
|
|
39141
|
+
"Provider API key header: authorization or x-api-key",
|
|
39142
|
+
"authorization"
|
|
39143
|
+
).option("--provider <provider>", "Provider label", "lm-studio").option("--model <id>", "Exact model id exposed by the local runtime").option("--prefer-model <text>", "Fallback local model substring when exact model is unset").option(
|
|
38960
39144
|
"--role <role>",
|
|
38961
39145
|
"Worker role; for example coding, documentation, tests, or review",
|
|
38962
39146
|
"coding"
|
|
@@ -38987,6 +39171,8 @@ localWorkers.command("probe").description("Probe an OpenAI-compatible endpoint a
|
|
|
38987
39171
|
reasoning: options.reasoning ? options.reasoning.toLowerCase() : void 0,
|
|
38988
39172
|
contextWindow: options.contextWindow,
|
|
38989
39173
|
writeScope: options.writeScope,
|
|
39174
|
+
apiKeyEnv: options.apiKeyEnv,
|
|
39175
|
+
apiKeyHeader: options.apiKeyHeader,
|
|
38990
39176
|
json: options.json
|
|
38991
39177
|
});
|
|
38992
39178
|
});
|
package/docs/FULL_REFERENCE.md
CHANGED
|
@@ -464,7 +464,8 @@ snipara-companion workers local add \
|
|
|
464
464
|
--role coding \
|
|
465
465
|
--provider lm-studio \
|
|
466
466
|
--base-url http://127.0.0.1:1234 \
|
|
467
|
-
--model openai/gpt-oss-20b
|
|
467
|
+
--model openai/gpt-oss-20b \
|
|
468
|
+
--api-key-env LM_STUDIO_API_KEY
|
|
468
469
|
```
|
|
469
470
|
|
|
470
471
|
The declaration is written under `.snipara/workers/<worker-id>.json`; Companion
|
|
@@ -499,7 +500,11 @@ Do not store secrets in worker profiles. Local endpoints such as
|
|
|
499
500
|
`http://127.0.0.1:1234` are safe to commit when they contain no credentials, but
|
|
500
501
|
cloud CLI transports or authenticated endpoints must reference secrets through
|
|
501
502
|
environment variables rather than embedding API keys, bearer tokens, passwords,
|
|
502
|
-
or private URLs directly in `.snipara/workers/*.json`.
|
|
503
|
+
or private URLs directly in `.snipara/workers/*.json`. `--api-key-env` stores
|
|
504
|
+
only the variable name; pair it with `--api-key-header authorization` (default)
|
|
505
|
+
or `--api-key-header x-api-key`. Native Codex and Claude profiles use their
|
|
506
|
+
host-managed credentials. A generic `cli://command` profile fails closed unless
|
|
507
|
+
the command maps to a supported Codex or Claude adapter.
|
|
503
508
|
|
|
504
509
|
Use `workers local probe` to query a local endpoint and preview a declaration
|
|
505
510
|
proposal before committing it:
|
|
@@ -559,6 +564,24 @@ snipara-orchestrator local-model-catalog \
|
|
|
559
564
|
--json > .snipara/local-devstral-runtime-catalog.json
|
|
560
565
|
```
|
|
561
566
|
|
|
567
|
+
For a remote OpenAI-compatible runtime, use an explicit allowlist and an
|
|
568
|
+
environment-backed key when running the native host:
|
|
569
|
+
|
|
570
|
+
```bash
|
|
571
|
+
snipara-orchestrator host run \
|
|
572
|
+
--adapter openai_compatible \
|
|
573
|
+
--base-url https://provider.example.com --allow-remote \
|
|
574
|
+
--api-key-env PROVIDER_API_KEY --api-key-header authorization \
|
|
575
|
+
--model provider/coder --task "Bounded task" --workspace . \
|
|
576
|
+
--write-scope docs/** --proof "git diff --check" --execute
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Native host proof commands run automatically after dispatch. Use
|
|
580
|
+
`--no-run-proof` only when a reviewer will validate the receipt; the state then
|
|
581
|
+
remains `verification_required`. Use `--require-approval` with both an approval
|
|
582
|
+
receipt id and `--approval-receipt-file <json>` for unattended execution; an id
|
|
583
|
+
alone never bypasses the approval gate.
|
|
584
|
+
|
|
562
585
|
The local catalog records the OpenAI-compatible routes exposed by LM Studio:
|
|
563
586
|
`GET /v1/models`, `POST /v1/responses`, `POST /v1/chat/completions`,
|
|
564
587
|
`POST /v1/completions`, and `POST /v1/embeddings`. `--prefer-model devstral`
|
|
@@ -1335,6 +1358,7 @@ snipara-companion workers execute \
|
|
|
1335
1358
|
--write-scope docs/features/PROJECT_INTELLIGENCE.md \
|
|
1336
1359
|
--acceptance "docs match shipped behavior" \
|
|
1337
1360
|
--proof "pnpm --filter @snipara/web type-check" \
|
|
1361
|
+
--output-fragment "expected output line" \
|
|
1338
1362
|
--project-id proj_123 \
|
|
1339
1363
|
--json
|
|
1340
1364
|
```
|
|
@@ -1345,6 +1369,8 @@ values for real execution. A legacy `--command` string still requires a fresh
|
|
|
1345
1369
|
approval receipt and cannot consume delegated trust. High-risk commands are
|
|
1346
1370
|
blocked locally, and successful low-risk commands produce
|
|
1347
1371
|
`verification_required` receipts so proof review remains explicit. When
|
|
1372
|
+
`--output-fragment` is provided, every declared fragment must appear in stdout;
|
|
1373
|
+
missing fragments fail the receipt closed and are listed in the contract.
|
|
1348
1374
|
`--project-id` is provided,
|
|
1349
1375
|
Companion also writes a local Unified Receipt Ledger projection under
|
|
1350
1376
|
`.snipara/unified-receipts/`; use `--unified-output <file>` to choose the sidecar
|