snipara-companion 1.4.21 → 1.4.22
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 +33 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +91 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -127,6 +127,7 @@ snipara-companion brief --task "ship auth hardening" --changed-files src/auth.ts
|
|
|
127
127
|
snipara-companion timeline
|
|
128
128
|
snipara-companion workflow phase-commit build --summary "tests green"
|
|
129
129
|
snipara-companion workflow impact-gate
|
|
130
|
+
snipara-companion workflow run --adaptive-routing-dry-run --route-local-workers "document a scoped change"
|
|
130
131
|
snipara-companion verify --changed-files src/auth.ts --diff-summary "auth hardening"
|
|
131
132
|
snipara-companion run --task "ship auth hardening" --changed-files src/auth.ts --release
|
|
132
133
|
snipara-companion handoff --summary "status command shipped" --next "publish package"
|
|
@@ -141,6 +142,9 @@ snipara-companion workflow resume --include-session-context
|
|
|
141
142
|
- `workflow impact-gate` audits committed local workflow phases that are ahead
|
|
142
143
|
of upstream but not pushed. It does not push, and dirty working-tree files are
|
|
143
144
|
reported separately from the committed diff.
|
|
145
|
+
- `workflow run --adaptive-routing-dry-run` prints an Adaptive Work Routing
|
|
146
|
+
card. Add `--route-local-workers` when a strong planner should keep deep
|
|
147
|
+
reasoning while a local worker handles scoped execution.
|
|
144
148
|
- `verify` builds a transparent verification plan from companion code impact
|
|
145
149
|
signals plus local package scripts. It recommends checks; it does not claim to
|
|
146
150
|
execute them.
|
|
@@ -167,6 +171,35 @@ if the hosted call still times out. A hosted final-commit timeout does not modif
|
|
|
167
171
|
Git state. Custom final-commit categories are namespaced under `final-commit`
|
|
168
172
|
before the hosted call so they stay on the handoff-only path.
|
|
169
173
|
|
|
174
|
+
## Adaptive Work Routing
|
|
175
|
+
|
|
176
|
+
Adaptive Work Routing is a recommendation-first path for routing scoped work to
|
|
177
|
+
the right worker class, endpoint type, and cost profile without hardcoding model
|
|
178
|
+
names in the CLI.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
snipara-companion workflow run \
|
|
182
|
+
--mode full \
|
|
183
|
+
--adaptive-routing-dry-run \
|
|
184
|
+
--route-local-workers \
|
|
185
|
+
--routing-worker-role coding \
|
|
186
|
+
--routing-preferred-endpoint local \
|
|
187
|
+
--routing-allowed-endpoint local \
|
|
188
|
+
--routing-allowed-endpoint cloud \
|
|
189
|
+
--planner-retains-reasoning \
|
|
190
|
+
"Update documentation for the new gateway"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The output is a routing card and handoff metadata. Companion calls the hosted
|
|
194
|
+
`snipara_adaptive_routing_catalog` tool when project auth is configured, records
|
|
195
|
+
the sanitized runtime catalog in the handoff, and falls back to local dry-run
|
|
196
|
+
metadata when the hosted gateway is unavailable. It does not silently spawn
|
|
197
|
+
workers. The stable contract is provider-neutral requirements such as worker
|
|
198
|
+
role, reasoning depth, context budget, endpoint type, write scope, and fallback.
|
|
199
|
+
Project credentials stay server-side behind the hosted gateway; local endpoints
|
|
200
|
+
such as Ollama, LM Studio, AnythingLLM, or other OpenAI-compatible servers must
|
|
201
|
+
be reachable from the worker execution environment.
|
|
202
|
+
|
|
170
203
|
## Verification Plans
|
|
171
204
|
|
|
172
205
|
Use `verify` when an agent asks what to prove before handoff or release:
|
package/dist/index.d.ts
CHANGED
|
@@ -2837,10 +2837,24 @@ interface AdaptiveRoutingCard {
|
|
|
2837
2837
|
reasons: string[];
|
|
2838
2838
|
warnings: string[];
|
|
2839
2839
|
}
|
|
2840
|
+
interface AdaptiveRoutingGatewayStatus {
|
|
2841
|
+
source: "hosted_mcp";
|
|
2842
|
+
success: boolean;
|
|
2843
|
+
resolutionStatus?: string;
|
|
2844
|
+
candidateCount: number;
|
|
2845
|
+
fallback?: string;
|
|
2846
|
+
warnings: string[];
|
|
2847
|
+
}
|
|
2848
|
+
interface AdaptiveRoutingRuntimeCatalog {
|
|
2849
|
+
version?: string;
|
|
2850
|
+
candidates: Array<Record<string, unknown>>;
|
|
2851
|
+
}
|
|
2840
2852
|
interface AdaptiveWorkRoutingRecommendation {
|
|
2841
2853
|
workProfile: AdaptiveWorkProfile;
|
|
2842
2854
|
requirements: AdaptiveModelRequirements;
|
|
2843
2855
|
routingCard: AdaptiveRoutingCard;
|
|
2856
|
+
gateway?: AdaptiveRoutingGatewayStatus;
|
|
2857
|
+
runtimeCatalog?: AdaptiveRoutingRuntimeCatalog;
|
|
2844
2858
|
}
|
|
2845
2859
|
interface AdaptiveWorkRoutingOptions {
|
|
2846
2860
|
query: string;
|
|
@@ -2877,6 +2891,8 @@ interface OrchestratorHandoffArtifact {
|
|
|
2877
2891
|
workProfile?: AdaptiveWorkProfile;
|
|
2878
2892
|
requirements?: AdaptiveModelRequirements;
|
|
2879
2893
|
routingCard?: AdaptiveRoutingCard;
|
|
2894
|
+
gateway?: AdaptiveRoutingGatewayStatus;
|
|
2895
|
+
runtimeCatalog?: AdaptiveRoutingRuntimeCatalog;
|
|
2880
2896
|
};
|
|
2881
2897
|
task: {
|
|
2882
2898
|
title: string;
|
package/dist/index.js
CHANGED
|
@@ -11144,7 +11144,9 @@ function buildOrchestratorHandoff(options) {
|
|
|
11144
11144
|
...options.adaptiveRouting ? {
|
|
11145
11145
|
workProfile: options.adaptiveRouting.workProfile,
|
|
11146
11146
|
requirements: options.adaptiveRouting.requirements,
|
|
11147
|
-
routingCard: options.adaptiveRouting.routingCard
|
|
11147
|
+
routingCard: options.adaptiveRouting.routingCard,
|
|
11148
|
+
...options.adaptiveRouting.gateway ? { gateway: options.adaptiveRouting.gateway } : {},
|
|
11149
|
+
...options.adaptiveRouting.runtimeCatalog ? { runtimeCatalog: options.adaptiveRouting.runtimeCatalog } : {}
|
|
11148
11150
|
} : {}
|
|
11149
11151
|
},
|
|
11150
11152
|
task: {
|
|
@@ -14648,6 +14650,20 @@ function stringValue5(value) {
|
|
|
14648
14650
|
const stringified = String(value).trim();
|
|
14649
14651
|
return stringified || void 0;
|
|
14650
14652
|
}
|
|
14653
|
+
function numberValue5(value) {
|
|
14654
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
14655
|
+
return value;
|
|
14656
|
+
}
|
|
14657
|
+
const text = stringValue5(value);
|
|
14658
|
+
if (!text) {
|
|
14659
|
+
return void 0;
|
|
14660
|
+
}
|
|
14661
|
+
const parsed = Number(text);
|
|
14662
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
14663
|
+
}
|
|
14664
|
+
function uniqueStrings3(values) {
|
|
14665
|
+
return Array.from(new Set(values.filter((value) => value.trim().length > 0)));
|
|
14666
|
+
}
|
|
14651
14667
|
function normalizeEnum(value) {
|
|
14652
14668
|
return stringValue5(value)?.replace(/[-\s]/g, "_").toUpperCase() ?? "";
|
|
14653
14669
|
}
|
|
@@ -17064,6 +17080,12 @@ function printAdaptiveRoutingRecommendation(routing) {
|
|
|
17064
17080
|
if (routing.requirements.plannerRetainsReasoning) {
|
|
17065
17081
|
printKeyValue("Planner retains reasoning:", "yes");
|
|
17066
17082
|
}
|
|
17083
|
+
if (routing.gateway) {
|
|
17084
|
+
printKeyValue(
|
|
17085
|
+
"Hosted catalog:",
|
|
17086
|
+
routing.gateway.success ? `${routing.gateway.candidateCount} candidate(s), ${routing.gateway.resolutionStatus ?? "ready"}` : "unavailable"
|
|
17087
|
+
);
|
|
17088
|
+
}
|
|
17067
17089
|
if (routing.routingCard.reasons.length > 0) {
|
|
17068
17090
|
console.log("Reasons:");
|
|
17069
17091
|
for (const reason of routing.routingCard.reasons) {
|
|
@@ -17077,6 +17099,73 @@ function printAdaptiveRoutingRecommendation(routing) {
|
|
|
17077
17099
|
}
|
|
17078
17100
|
}
|
|
17079
17101
|
}
|
|
17102
|
+
async function enrichAdaptiveRoutingWithHostedCatalog(client, routing) {
|
|
17103
|
+
try {
|
|
17104
|
+
const result = await client.callTool(
|
|
17105
|
+
"snipara_adaptive_routing_catalog",
|
|
17106
|
+
{
|
|
17107
|
+
work_profile: routing.workProfile,
|
|
17108
|
+
model_requirements: routing.requirements,
|
|
17109
|
+
limit: 20
|
|
17110
|
+
}
|
|
17111
|
+
);
|
|
17112
|
+
const catalog = normalizeAdaptiveRoutingCatalog(result.catalog);
|
|
17113
|
+
const warnings = normalizeStringArray3(result.warnings) ?? [];
|
|
17114
|
+
const candidateCount = numberValue5(result.resolution?.candidate_count) ?? numberValue5(result.resolution?.candidateCount) ?? catalog.candidates.length;
|
|
17115
|
+
const gateway = {
|
|
17116
|
+
source: "hosted_mcp",
|
|
17117
|
+
success: result.success !== false,
|
|
17118
|
+
resolutionStatus: stringValue5(result.resolution?.status),
|
|
17119
|
+
candidateCount,
|
|
17120
|
+
fallback: stringValue5(result.fallback) ?? stringValue5(result.resolution?.fallback) ?? "main_agent",
|
|
17121
|
+
warnings
|
|
17122
|
+
};
|
|
17123
|
+
const reasons = [
|
|
17124
|
+
...routing.routingCard.reasons,
|
|
17125
|
+
candidateCount > 0 ? `hosted adaptive routing catalog returned ${candidateCount} candidate(s)` : "hosted adaptive routing catalog returned no candidates and will fail closed"
|
|
17126
|
+
];
|
|
17127
|
+
return {
|
|
17128
|
+
...routing,
|
|
17129
|
+
gateway,
|
|
17130
|
+
runtimeCatalog: catalog,
|
|
17131
|
+
routingCard: {
|
|
17132
|
+
...routing.routingCard,
|
|
17133
|
+
reasons: uniqueStrings3(reasons),
|
|
17134
|
+
warnings: uniqueStrings3([...routing.routingCard.warnings, ...warnings])
|
|
17135
|
+
}
|
|
17136
|
+
};
|
|
17137
|
+
} catch (error) {
|
|
17138
|
+
const warning = `Hosted adaptive routing catalog unavailable; keeping local dry-run metadata (${toPreview(error)}).`;
|
|
17139
|
+
return {
|
|
17140
|
+
...routing,
|
|
17141
|
+
gateway: {
|
|
17142
|
+
source: "hosted_mcp",
|
|
17143
|
+
success: false,
|
|
17144
|
+
resolutionStatus: "unavailable",
|
|
17145
|
+
candidateCount: 0,
|
|
17146
|
+
fallback: "main_agent",
|
|
17147
|
+
warnings: [warning]
|
|
17148
|
+
},
|
|
17149
|
+
routingCard: {
|
|
17150
|
+
...routing.routingCard,
|
|
17151
|
+
warnings: uniqueStrings3([...routing.routingCard.warnings, warning])
|
|
17152
|
+
}
|
|
17153
|
+
};
|
|
17154
|
+
}
|
|
17155
|
+
}
|
|
17156
|
+
function normalizeAdaptiveRoutingCatalog(value) {
|
|
17157
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
17158
|
+
return { candidates: [] };
|
|
17159
|
+
}
|
|
17160
|
+
const record = value;
|
|
17161
|
+
const candidates = Array.isArray(record.candidates) ? record.candidates.filter(
|
|
17162
|
+
(candidate) => Boolean(candidate) && typeof candidate === "object" && !Array.isArray(candidate)
|
|
17163
|
+
) : [];
|
|
17164
|
+
return {
|
|
17165
|
+
version: stringValue5(record.version),
|
|
17166
|
+
candidates
|
|
17167
|
+
};
|
|
17168
|
+
}
|
|
17080
17169
|
function printUploadResult(path20, result) {
|
|
17081
17170
|
printKeyValue("Uploaded:", path20);
|
|
17082
17171
|
printCompactObject(result, ["message", "document_id", "documentId", "version", "status"]);
|
|
@@ -18551,7 +18640,7 @@ async function workflowRunCommand(options) {
|
|
|
18551
18640
|
ensureConfigured();
|
|
18552
18641
|
const client = createClient(2e4);
|
|
18553
18642
|
const adaptiveRoutingRequested = shouldBuildAdaptiveRouting(options);
|
|
18554
|
-
const adaptiveRouting = adaptiveRoutingRequested ? buildWorkflowAdaptiveRouting(options) : null;
|
|
18643
|
+
const adaptiveRouting = adaptiveRoutingRequested ? await enrichAdaptiveRoutingWithHostedCatalog(client, buildWorkflowAdaptiveRouting(options)) : null;
|
|
18555
18644
|
const orchestratorRecommendation = getOrchestratorRecommendation(options.query, options.mode, {
|
|
18556
18645
|
policyAutoRoute: options.autoRouteOrchestrator,
|
|
18557
18646
|
policySource: options.orchestratorPolicySource,
|
package/package.json
CHANGED