@mcoda/codali 0.1.119 → 0.1.121

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.
@@ -1 +1 @@
1
- {"version":3,"file":"GatewayPlanner.d.ts","sourceRoot":"","sources":["../../src/gateway/GatewayPlanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GatewayPlanner.d.ts","sourceRoot":"","sources":["../../src/gateway/GatewayPlanner.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { validateCodaliGatewayPlannerOutput, } from "./CodaliGatewaySchemas.js";
2
2
  import { compileCodaliGatewayPolicy, } from "./GatewayPolicyCompiler.js";
3
3
  import { CODALI_GATEWAY_SECURITY_PROMPT_HARDENING } from "./GatewaySecurityPolicy.js";
4
+ import { requestTouchesOwnData } from "./GroundingMode.js";
4
5
  import { renderCapabilityLines, renderToolLines } from "./ToolExposure.js";
5
6
  import { buildTemporalContext, renderTemporalContext } from "./TemporalContext.js";
6
7
  export class CodaliGatewayPlannerError extends Error {
@@ -417,6 +418,12 @@ export const resolveToolNameAgainst = (candidate, available) => {
417
418
  const bySuffix = available.filter((tool) => tool.toLowerCase().endsWith(`:${lower}`));
418
419
  return bySuffix.length === 1 ? bySuffix[0] : undefined;
419
420
  };
421
+ /**
422
+ * Whether a tool name belongs to a connector into someone's account, as opposed
423
+ * to a repository search or the public web. Namespaced transports are the
424
+ * connectors: `mcp:github:list_issues`, `http:jira:search_issues`.
425
+ */
426
+ const isOwnedSystemConnector = (tool) => tool.startsWith("mcp:") || tool.startsWith("http:");
420
427
  const allowedToolNames = (compilation) => [...compilation.effectiveAllowedTools].sort();
421
428
  /**
422
429
  * Capability names the classifier selected for stage-2 tool expansion. Absent
@@ -518,7 +525,16 @@ export const buildCodaliGatewayClassifierMessages = (input) => {
518
525
  };
519
526
  export const buildCodaliGatewayPlannerMessages = (input, classifier) => {
520
527
  const policy = input.policyCompilation ?? compileCodaliGatewayPolicy({ request: input.request });
521
- const tools = allowedToolNames(policy);
528
+ // A connector reaches into the user's own account, so it is only worth
529
+ // showing when the request is about their data. Left in view for every
530
+ // question, the planner picked by surface resemblance — a question about a
531
+ // company's chief executive went to a GitHub user search, and one about a
532
+ // language's newest release went to `get_latest_release`. Withholding them
533
+ // is a narrowing, not a denial: an explicitly allowed tool is still allowed,
534
+ // this only stops it being suggested for work it cannot do.
535
+ const tools = requestTouchesOwnData(input.request.query, classifier)
536
+ ? allowedToolNames(policy)
537
+ : allowedToolNames(policy).filter((tool) => !isOwnedSystemConnector(tool));
522
538
  // Stage 2 of two-level exposure: expand full schemas, but only for the
523
539
  // capabilities the classifier selected.
524
540
  const exposure = renderToolLines(tools, input.toolDescriptions, classifier.capabilities);
@@ -32,4 +32,14 @@ export interface GroundingDecisionInput {
32
32
  classifier: Pick<CodaliGatewayClassifierOutput, "needsPrivateData" | "needsFreshData" | "needsDocdex" | "needsAppTools">;
33
33
  }
34
34
  export declare const decideGroundingMode: (input: GroundingDecisionInput) => GroundingDecision;
35
+ /**
36
+ * Whether the request is about data the user owns, and so whether the
37
+ * connectors that reach their accounts should be offered at all.
38
+ *
39
+ * Deliberately generous: a wrong "yes" offers a tool the planner may ignore,
40
+ * while a wrong "no" hides the only tool that could have answered. So the
41
+ * classifier's own judgement is honoured first, and either naming the system or
42
+ * claiming the data is enough.
43
+ */
44
+ export declare const requestTouchesOwnData: (query: string, classifier: Pick<GroundingDecisionInput["classifier"], "needsPrivateData" | "needsAppTools">) => boolean;
35
45
  //# sourceMappingURL=GroundingMode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GroundingMode.d.ts","sourceRoot":"","sources":["../../src/gateway/GroundingMode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,IAAI,CACd,6BAA6B,EAC7B,kBAAkB,GAAG,gBAAgB,GAAG,aAAa,GAAG,eAAe,CACxE,CAAC;CACH;AAiDD,eAAO,MAAM,mBAAmB,GAC9B,OAAO,sBAAsB,KAC5B,iBAoCF,CAAC"}
1
+ {"version":3,"file":"GroundingMode.d.ts","sourceRoot":"","sources":["../../src/gateway/GroundingMode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,IAAI,CACd,6BAA6B,EAC7B,kBAAkB,GAAG,gBAAgB,GAAG,aAAa,GAAG,eAAe,CACxE,CAAC;CACH;AAiDD,eAAO,MAAM,mBAAmB,GAC9B,OAAO,sBAAsB,KAC5B,iBAoCF,CAAC;AAcF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,MAAM,EACb,YAAY,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,EAAE,kBAAkB,GAAG,eAAe,CAAC,KAC3F,OAImC,CAAC"}
@@ -67,3 +67,26 @@ export const decideGroundingMode = (input) => {
67
67
  }
68
68
  return { mode: "grounded", reason: "default" };
69
69
  };
70
+ /**
71
+ * Systems a request has to name before a connector to them is worth offering.
72
+ *
73
+ * A product connector reaches into somebody's account. Offering every one of
74
+ * them to every question invited the planner to pick by surface resemblance:
75
+ * asked who currently runs Microsoft it called `mcp:github:search_users`, and
76
+ * asked for the newest Node.js release it called `get_latest_release`. Both are
77
+ * public facts about a company, and neither is in anyone's account.
78
+ */
79
+ const OWNED_SYSTEM_NOUNS = /\b(?:github|gitlab|bitbucket|jira|confluence|outlook|teams|calendar|inbox|mailbox|repository|repositories|repo|commit|commits|branch|branches|pull request|merge request|issue|issues|ticket|tickets|workspace|tenant)\b/i;
80
+ /**
81
+ * Whether the request is about data the user owns, and so whether the
82
+ * connectors that reach their accounts should be offered at all.
83
+ *
84
+ * Deliberately generous: a wrong "yes" offers a tool the planner may ignore,
85
+ * while a wrong "no" hides the only tool that could have answered. So the
86
+ * classifier's own judgement is honoured first, and either naming the system or
87
+ * claiming the data is enough.
88
+ */
89
+ export const requestTouchesOwnData = (query, classifier) => classifier.needsPrivateData === true ||
90
+ classifier.needsAppTools === true ||
91
+ POSSESSIVE.test(query ?? "") ||
92
+ OWNED_SYSTEM_NOUNS.test(query ?? "");
@@ -1 +1 @@
1
- {"version":3,"file":"DocdexTools.d.ts","sourceRoot":"","sources":["../../../src/tools/docdex/DocdexTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAuFjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,GAAG,SAAS,EACzB,gBAAgB,MAAM,KACrB,MAAM,GAAG,SAWX,CAAC;AAyBF,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,QAAO,IAG1C,CAAC;AAqJF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,YAAY,EACpB,UAAS,iBAAsB,KAC9B,cAAc,EAAgE,CAAC"}
1
+ {"version":3,"file":"DocdexTools.d.ts","sourceRoot":"","sources":["../../../src/tools/docdex/DocdexTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAuFjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,GAAG,SAAS,EACzB,gBAAgB,MAAM,KACrB,MAAM,GAAG,SAWX,CAAC;AAwCF,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,QAAO,IAG1C,CAAC;AA+JF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,YAAY,EACpB,UAAS,iBAAsB,KAC9B,cAAc,EAAgE,CAAC"}
@@ -123,8 +123,23 @@ export const toRepoRelativePath = (value, workspaceRoot) => {
123
123
  * the fallback is deliberately short, because staying closed too long is a
124
124
  * self-inflicted outage and reopening early costs one wasted call.
125
125
  */
126
- const WEB_QUOTA_STATUSES = new Set([401, 402, 403, 429]);
126
+ /**
127
+ * Two kinds of refusal, and they deserve different patience.
128
+ *
129
+ * A spent quota or a rejected credential will still be spent and still be
130
+ * rejected in a minute, so the sensible default is long. A rate limit or a
131
+ * service restarting is over in seconds, and blocking for a quarter of an hour
132
+ * because a container was recreated would turn a blip into an outage of our
133
+ * own making.
134
+ *
135
+ * `Retry-After` overrides both, because the provider knows and we are guessing.
136
+ * The upstream gateway now answers a cold start with 503 and a `Retry-After`
137
+ * rather than a bodyless 502, which is precisely the case this handles.
138
+ */
139
+ const WEB_EXHAUSTED_STATUSES = new Set([401, 402, 403]);
140
+ const WEB_TRANSIENT_STATUSES = new Set([429, 503]);
127
141
  const DEFAULT_WEB_BACKOFF_MS = 15 * 60000;
142
+ const TRANSIENT_WEB_BACKOFF_MS = 30000;
128
143
  const MAX_WEB_BACKOFF_MS = 60 * 60000;
129
144
  let webUnavailableUntilMs = 0;
130
145
  let webUnavailableReason = "";
@@ -150,15 +165,25 @@ const retryAfterMsFrom = (error) => {
150
165
  }
151
166
  return undefined;
152
167
  };
153
- const isWebQuotaRefusal = (error) => {
168
+ const webRefusalStatus = (error) => {
154
169
  const status = isRecord(error) && typeof error.status === "number" ? error.status : undefined;
155
- return status !== undefined && WEB_QUOTA_STATUSES.has(status);
170
+ if (status === undefined)
171
+ return undefined;
172
+ return WEB_EXHAUSTED_STATUSES.has(status) || WEB_TRANSIENT_STATUSES.has(status)
173
+ ? status
174
+ : undefined;
156
175
  };
176
+ const isWebQuotaRefusal = (error) => webRefusalStatus(error) !== undefined;
157
177
  const noteWebRefusal = (error) => {
158
- const backoff = Math.min(retryAfterMsFrom(error) ?? DEFAULT_WEB_BACKOFF_MS, MAX_WEB_BACKOFF_MS);
178
+ const status = webRefusalStatus(error);
179
+ const fallback = status !== undefined && WEB_TRANSIENT_STATUSES.has(status)
180
+ ? TRANSIENT_WEB_BACKOFF_MS
181
+ : DEFAULT_WEB_BACKOFF_MS;
182
+ const backoff = Math.min(retryAfterMsFrom(error) ?? fallback, MAX_WEB_BACKOFF_MS);
159
183
  webUnavailableUntilMs = Date.now() + backoff;
160
- const status = isRecord(error) && typeof error.status === "number" ? error.status : "unknown";
161
- webUnavailableReason = `provider returned ${status}; not retrying for ${Math.round(backoff / 60000)}m`;
184
+ webUnavailableReason =
185
+ `provider returned ${status ?? "unknown"}; not retrying for ` +
186
+ (backoff < 60000 ? `${Math.round(backoff / 1000)}s` : `${Math.round(backoff / 60000)}m`);
162
187
  };
163
188
  const webResearchBlocked = () => Date.now() < webUnavailableUntilMs ? webUnavailableReason : undefined;
164
189
  /** Pages to keep from a web research call, and how much of each. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcoda/codali",
3
- "version": "0.1.119",
3
+ "version": "0.1.121",
4
4
  "description": "Standalone tool-runner adapter for mcoda.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,8 +35,8 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@modelcontextprotocol/sdk": "1.30.0",
38
- "@mcoda/db": "0.1.119",
39
- "@mcoda/shared": "0.1.119"
38
+ "@mcoda/db": "0.1.121",
39
+ "@mcoda/shared": "0.1.121"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.json",