@code-yeongyu/senpi 2026.10.25-4 → 2026.10.26-2
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 +47 -0
- package/dist/bundle/chunks/{anthropic-messages-WBASBTIW.js → anthropic-messages-ODSFJCXR.js} +3 -3
- package/dist/bundle/chunks/{args-B444OQBK.js → args-SWKJAYQD.js} +1 -1
- package/dist/bundle/chunks/azure-openai-responses-REGXS4XO.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
- package/dist/bundle/chunks/chunk-2XF6W6F6.js +410 -0
- package/dist/bundle/chunks/{chunk-WDPQ6CZJ.js → chunk-4QVORFQ2.js} +1 -1
- package/dist/bundle/chunks/{chunk-6AOVUTUR.js → chunk-5W3DTM2J.js} +2 -2
- package/dist/bundle/chunks/{chunk-E6WYH3ZL.js → chunk-6GAMRAVM.js} +9 -7
- package/dist/bundle/chunks/{chunk-N7IN46Q5.js → chunk-7IZH2KQX.js} +9 -7
- package/dist/bundle/chunks/{chunk-7GZUFOM3.js → chunk-ARSENVDY.js} +1 -1
- package/dist/bundle/chunks/{chunk-STMXIBXF.js → chunk-CNDPCYNT.js} +1 -1
- package/dist/bundle/chunks/{chunk-XF3LJC3O.js → chunk-CYOHFREV.js} +1 -1
- package/dist/bundle/chunks/{chunk-E6D4RIT7.js → chunk-DNDZPKIQ.js} +2 -2
- package/dist/bundle/chunks/{chunk-E4LBKOZG.js → chunk-EQNUL2WB.js} +4 -4
- package/dist/bundle/chunks/{chunk-2RB5EL4X.js → chunk-ESNSRUW4.js} +1 -1
- package/dist/bundle/chunks/{chunk-4AOMNOGY.js → chunk-FQDARFHT.js} +1 -1
- package/dist/bundle/chunks/{chunk-BWA4FVFW.js → chunk-GPPOPK76.js} +3 -3
- package/dist/bundle/chunks/{chunk-SBGIXMX3.js → chunk-GWGNVYPB.js} +1 -1
- package/dist/bundle/chunks/{chunk-KKD4CYCI.js → chunk-H4WJ4LY3.js} +1 -1
- package/dist/bundle/chunks/{chunk-V2UYXTRR.js → chunk-HWTD4QF3.js} +1 -1
- package/dist/bundle/chunks/chunk-I2WFLKZ2.js +5 -0
- package/dist/bundle/chunks/{chunk-WD6WBYC5.js → chunk-IHKHCWWG.js} +1 -1
- package/dist/bundle/chunks/{chunk-T36LJ6MW.js → chunk-IY4G44MN.js} +1 -1
- package/dist/bundle/chunks/{chunk-BZ7726QO.js → chunk-J2YAYTB2.js} +1 -1
- package/dist/bundle/chunks/{chunk-UFJ2K7Q7.js → chunk-JH7MVRNJ.js} +1 -1
- package/dist/bundle/chunks/chunk-KBSFTXAT.js +2 -0
- package/dist/bundle/chunks/{chunk-OLCDIITS.js → chunk-KRO63T4Q.js} +1 -1
- package/dist/bundle/chunks/{chunk-TTU2RNVX.js → chunk-KTDIIF2F.js} +1 -1
- package/dist/bundle/chunks/{chunk-KNVNKDER.js → chunk-L2O6K3SJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-3BTN337S.js → chunk-NDNIMC5W.js} +1 -1
- package/dist/bundle/chunks/{chunk-ITGYN22E.js → chunk-ODRGPC5S.js} +1 -1
- package/dist/bundle/chunks/{chunk-4MOZXOJX.js → chunk-PDG4XWO2.js} +1 -1
- package/dist/bundle/chunks/{chunk-3QCYBOKN.js → chunk-PPECSSWX.js} +1 -1
- package/dist/bundle/chunks/{chunk-4P7WARQZ.js → chunk-PY4ZQHTN.js} +1 -1
- package/dist/bundle/chunks/{chunk-C2MQ4QXN.js → chunk-RPW3XQW3.js} +48 -42
- package/dist/bundle/chunks/{chunk-JMOUU75H.js → chunk-RQ5JTXUC.js} +1 -1
- package/dist/bundle/chunks/chunk-TQ67PB7U.js +13 -0
- package/dist/bundle/chunks/{chunk-5JJDR6XI.js → chunk-UJPG4ROT.js} +1 -1
- package/dist/bundle/chunks/{chunk-FHXR4ZAC.js → chunk-XM36IFP3.js} +1 -1
- package/dist/bundle/chunks/{chunk-PT6JJUN2.js → chunk-XMNPK472.js} +1 -1
- package/dist/bundle/chunks/{client-WTYEICLH.js → chunk-Y3TMJV3J.js} +3 -3
- package/dist/bundle/chunks/{chunk-GSSD3R5X.js → chunk-Z6BREXV3.js} +1 -1
- package/dist/bundle/chunks/{chunk-KXB5WIS5.js → chunk-Z6SAQ5O3.js} +1 -1
- package/dist/bundle/chunks/{chunk-LOIF6PHI.js → chunk-ZAUVY6ZC.js} +3 -3
- package/dist/bundle/chunks/{chunk-7CNOCJCN.js → chunk-ZP6JJDYV.js} +1 -1
- package/dist/bundle/chunks/cli-main-Q2GA53XM.js +3 -0
- package/dist/bundle/chunks/client-LOS6GSEW.js +2 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-K5H6BJP3.js → cloudflare-workers-ai-system-one-WDHT7BBV.js} +1 -1
- package/dist/bundle/chunks/cursor-agent.js +3 -3
- package/dist/bundle/chunks/devin-agent.js +3 -3
- package/dist/bundle/chunks/dispatch-5R3TYAYB.js +9 -0
- package/dist/bundle/chunks/google-generative-ai-FHYFXKLA.js +2 -0
- package/dist/bundle/chunks/google-vertex-5DWE5U5K.js +2 -0
- package/dist/bundle/chunks/{help-fast-path-3Z26DQSV.js → help-fast-path-FETLIF3W.js} +1 -1
- package/dist/bundle/chunks/host-command-XEB7SHT3.js +2 -0
- package/dist/bundle/chunks/{host-lifecycle-3VHHIGDL.js → host-lifecycle-HX3EGRRW.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +2 -2
- package/dist/bundle/chunks/{host-session-command-56XF6ACS.js → host-session-command-FFN52LXJ.js} +1 -1
- package/dist/bundle/chunks/{host-socket-request-QL2WEZTN.js → host-socket-request-K4LCUOUD.js} +1 -1
- package/dist/bundle/chunks/interactive-mode-5DEKY3YW.js +2 -0
- package/dist/bundle/chunks/{mcp-presenter-bootstrap-XUSCQVRC.js → mcp-presenter-bootstrap-FOMKF4TU.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-DH44NOYV.js → mistral-conversations-I2PI7DDF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-Z2CW4SDM.js → multi-session-host-OPR5VBFO.js} +6 -7
- package/dist/bundle/chunks/{openai-codex-responses-SERAFKAS.js → openai-codex-responses-WSEX6SH7.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-BZB5O45A.js → openai-completions-YCBHTBSS.js} +1 -1
- package/dist/bundle/chunks/openai-responses-GXNSQF4A.js +3 -0
- package/dist/bundle/chunks/{package-manager-cli-N55U6PEO.js → package-manager-cli-W55E3LHP.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-VXATX45B.js → pi-messages-O6GISIRW.js} +2 -2
- package/dist/bundle/chunks/{role-JVSBNKGE.js → role-SHIZQKK4.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-CBGCBYHV.js → rotation-stream-2PCZWNKF.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-IDUJTSYS.js +2 -0
- package/dist/bundle/chunks/{rpc-monitor-source-AE3C6EQV.js → rpc-monitor-source-DRZXJHTL.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-VS7CZC2J.js → schedule-command-B7RRSANU.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-LMZH5JLH.js +3 -0
- package/dist/bundle/chunks/{session-picker-E4KUJDLO.js → session-picker-DTGBOXDR.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +214 -205
- package/dist/bundle/chunks/{typesafe-system-one-P75WJ767.js → typesafe-system-one-XGYJJVSE.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/host-supervisor.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/cli/host-command-args.d.ts +1 -0
- package/dist/cli/host-command-args.js +5 -0
- package/dist/cli/host-command.js +7 -1
- package/dist/cli.js +21 -3
- package/dist/core/agent-session.d.ts +11 -1
- package/dist/core/agent-session.js +19 -2
- package/dist/core/extensions/builtin/compaction/index.js +7 -1
- package/dist/core/extensions/builtin/herdr/index.js +9 -5
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +6 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +25 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +3 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +50 -19
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +4 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth.js +19 -12
- package/dist/core/extensions/builtin/mcp/catalog-cache.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/catalog-cache.js +19 -6
- package/dist/core/extensions/builtin/mcp/catalog.d.ts +3 -2
- package/dist/core/extensions/builtin/mcp/catalog.js +20 -3
- package/dist/core/extensions/builtin/mcp/expose/call.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/expose/call.js +2 -1
- package/dist/core/extensions/builtin/mcp/expose/register.js +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js +11 -1
- package/dist/core/extensions/builtin/mcp/invocation.js +16 -2
- package/dist/core/extensions/builtin/mcp/modern/dispatch.js +1 -0
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.d.ts +4 -1
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.js +33 -35
- package/dist/core/extensions/builtin/mcp/modern/request.d.ts +1 -1
- package/dist/core/extensions/builtin/mcp/modern/request.js +4 -1
- package/dist/core/extensions/builtin/mcp/modern/sdk-bridge.js +18 -3
- package/dist/core/extensions/builtin/mcp/modern/stdio-probe.js +23 -0
- package/dist/core/extensions/builtin/mcp/modern/subscriptions.d.ts +14 -0
- package/dist/core/extensions/builtin/mcp/modern/subscriptions.js +226 -0
- package/dist/core/extensions/builtin/mcp/modern/tool-schema.d.ts +13 -0
- package/dist/core/extensions/builtin/mcp/modern/tool-schema.js +75 -0
- package/dist/core/extensions/builtin/mcp/modern/tools.d.ts +107 -0
- package/dist/core/extensions/builtin/mcp/modern/tools.js +53 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.js +4 -2
- package/dist/core/extensions/builtin/mcp/resources.js +4 -0
- package/dist/core/extensions/builtin/mcp/tool-client.d.ts +13 -0
- package/dist/core/extensions/builtin/mcp/tool-client.js +17 -0
- package/dist/core/extensions/builtin/mcp/tool-contracts.d.ts +19 -0
- package/dist/core/extensions/builtin/mcp/tool-contracts.js +2 -0
- package/dist/core/extensions/builtin/mcp/wrap.js +2 -2
- package/dist/core/extensions/builtin/permission-system/bash-command-segments.d.ts +37 -0
- package/dist/core/extensions/builtin/permission-system/bash-command-segments.js +899 -0
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/parsers.js +44 -10
- package/dist/core/extensions/builtin/terminal/extension-state.js +2 -1
- package/dist/core/extensions/builtin/vertex-model-garden/auth.d.ts +9 -0
- package/dist/core/extensions/builtin/vertex-model-garden/auth.js +17 -1
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.d.ts +6 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.js +6 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/lifecycle-children.d.ts +3 -1
- package/dist/core/lifecycle-children.js +79 -15
- package/dist/core/lifecycle-record.js +1 -24
- package/dist/core/lifecycle-session-binding.js +2 -1
- package/dist/core/lifecycle-wait-items.d.ts +17 -0
- package/dist/core/lifecycle-wait-items.js +72 -0
- package/dist/core/model-runtime.js +6 -1
- package/dist/core/provider-api-key-auth.d.ts +6 -1
- package/dist/core/provider-api-key-auth.js +11 -4
- package/dist/core/provider-composer.d.ts +8 -1
- package/dist/core/provider-composer.js +7 -3
- package/dist/core/sdk.js +4 -1
- package/dist/core/session-activity.js +2 -0
- package/dist/core/session-lifecycle-types.d.ts +20 -4
- package/dist/core/session-lifecycle.js +35 -4
- package/dist/core/structured-session-lane.d.ts +33 -0
- package/dist/core/structured-session-lane.js +62 -0
- package/dist/core/work-custody-record.d.ts +2 -1
- package/dist/core/work-custody-record.js +2 -0
- package/dist/core/work-obligations.d.ts +1 -1
- package/dist/core/work-obligations.js +8 -2
- package/dist/modes/interactive/session-control-commands.js +21 -4
- package/dist/modes/interactive/session-control-rpc-commands.d.ts +1 -1
- package/dist/modes/interactive/session-control-rpc-commands.js +19 -0
- package/dist/modes/json-event.d.ts +79 -1
- package/dist/modes/json-event.js +79 -1
- package/dist/modes/rpc/compact-content-index.d.ts +85 -0
- package/dist/modes/rpc/compact-content-index.js +254 -0
- package/dist/modes/rpc/compact-content-store.d.ts +59 -0
- package/dist/modes/rpc/compact-content-store.js +134 -0
- package/dist/modes/rpc/compact-index-pages.d.ts +12 -0
- package/dist/modes/rpc/compact-index-pages.js +31 -0
- package/dist/modes/rpc/compact-session-state.d.ts +83 -0
- package/dist/modes/rpc/compact-session-state.js +197 -0
- package/dist/modes/rpc/compact-spool-dir.d.ts +8 -0
- package/dist/modes/rpc/compact-spool-dir.js +94 -0
- package/dist/modes/rpc/compact-spool-storage.d.ts +53 -0
- package/dist/modes/rpc/compact-spool-storage.js +162 -0
- package/dist/modes/rpc/compact-storage-io.d.ts +28 -0
- package/dist/modes/rpc/compact-storage-io.js +25 -0
- package/dist/modes/rpc/compact-transition.d.ts +41 -0
- package/dist/modes/rpc/compact-transition.js +12 -0
- package/dist/modes/rpc/connection-handler.d.ts +4 -0
- package/dist/modes/rpc/connection-handler.js +51 -13
- package/dist/modes/rpc/connection-question-bridge.d.ts +2 -1
- package/dist/modes/rpc/connection-question-bridge.js +6 -2
- package/dist/modes/rpc/extension-ui-response.d.ts +7 -2
- package/dist/modes/rpc/extension-ui-response.js +27 -7
- package/dist/modes/rpc/get-snapshot.d.ts +18 -0
- package/dist/modes/rpc/get-snapshot.js +43 -0
- package/dist/modes/rpc/host-capabilities.js +3 -0
- package/dist/modes/rpc/host-ensure-start.js +6 -3
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +1 -0
- package/dist/modes/rpc/host-handoff.d.ts +2 -0
- package/dist/modes/rpc/host-handover-request.d.ts +1 -1
- package/dist/modes/rpc/host-handover-request.js +4 -3
- package/dist/modes/rpc/host-handover-wire.js +6 -0
- package/dist/modes/rpc/host-idle-handover.d.ts +2 -0
- package/dist/modes/rpc/host-idle-handover.js +3 -1
- package/dist/modes/rpc/host-observe-request.js +1 -0
- package/dist/modes/rpc/host-runner.d.ts +1 -0
- package/dist/modes/rpc/host-runner.js +9 -7
- package/dist/modes/rpc/host-successor.js +4 -0
- package/dist/modes/rpc/json-normal-value.d.ts +6 -0
- package/dist/modes/rpc/json-normal-value.js +100 -0
- package/dist/modes/rpc/mcp-presenter-bootstrap.js +5 -0
- package/dist/modes/rpc/media-placeholders.d.ts +9 -3
- package/dist/modes/rpc/media-placeholders.js +12 -4
- package/dist/modes/rpc/rpc-host-command-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-question-types.d.ts +1 -0
- package/dist/modes/rpc/rpc-read-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-session-command-types.d.ts +6 -0
- package/dist/modes/rpc/rpc-session-state-types.d.ts +3 -0
- package/dist/modes/rpc/rpc-session-state.js +2 -0
- package/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/dist/modes/rpc/security-presentations.js +2 -1
- package/dist/modes/rpc/session-attachment-gate.js +1 -0
- package/dist/modes/rpc/session-binding.js +30 -17
- package/dist/modes/rpc/session-command-activity.js +1 -0
- package/dist/modes/rpc/session-event-fanout.d.ts +1 -1
- package/dist/modes/rpc/session-event-fanout.js +17 -9
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.js +24 -5
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +2 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +15 -10
- package/dist/modes/rpc/session-held.js +1 -0
- package/dist/modes/rpc/session-record-stream.d.ts +3 -3
- package/dist/modes/rpc/session-record-stream.js +3 -3
- package/dist/modes/rpc/session-status-stream.d.ts +2 -1
- package/dist/modes/rpc/session-status-stream.js +8 -2
- package/dist/modes/rpc/session-status-subscriptions.d.ts +2 -1
- package/dist/modes/rpc/session-status-subscriptions.js +4 -0
- package/dist/modes/rpc/session-structured-lanes.d.ts +12 -0
- package/dist/modes/rpc/session-structured-lanes.js +24 -0
- package/dist/modes/rpc/session-worker-client.js +6 -5
- package/dist/modes/rpc/session-worker.js +5 -2
- package/dist/modes/rpc/snapshot-types.d.ts +29 -0
- package/dist/modes/rpc/snapshot-types.js +2 -0
- package/dist/modes/rpc/structured-session-records.d.ts +12 -0
- package/dist/modes/rpc/structured-session-records.js +88 -0
- package/dist/modes/rpc/ui-answer-ledger.d.ts +13 -0
- package/dist/modes/rpc/ui-answer-ledger.js +34 -0
- package/dist/senpi +21 -3
- package/docs/extensions.md +7 -1
- package/docs/mcp.md +20 -0
- package/docs/rpc.md +61 -2
- package/package.json +7 -6
- package/dist/bundle/chunks/azure-openai-responses-7I45DI72.js +0 -2
- package/dist/bundle/chunks/chunk-DMI55M2N.js +0 -2
- package/dist/bundle/chunks/chunk-DODH3N6U.js +0 -410
- package/dist/bundle/chunks/chunk-J37GRED2.js +0 -5
- package/dist/bundle/chunks/chunk-TBU6VYHN.js +0 -13
- package/dist/bundle/chunks/cli-main-YYH3IBC6.js +0 -3
- package/dist/bundle/chunks/dispatch-MXG5YWLV.js +0 -9
- package/dist/bundle/chunks/google-generative-ai-UM5Y7T6B.js +0 -2
- package/dist/bundle/chunks/google-vertex-OKU2VQHL.js +0 -2
- package/dist/bundle/chunks/host-command-TDLLHXVI.js +0 -2
- package/dist/bundle/chunks/interactive-mode-OEPULLZK.js +0 -2
- package/dist/bundle/chunks/openai-responses-TNHQ6SJS.js +0 -3
- package/dist/bundle/chunks/rpc-mode-ETXQWEB2.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-4LEIDIVI.js +0 -3
|
@@ -7,6 +7,8 @@ export type PermissionRequest = Pick<Request, "permission" | "patterns" | "alway
|
|
|
7
7
|
};
|
|
8
8
|
/** Parser function that extracts permission requests from tool input */
|
|
9
9
|
export type ToolPermissionParser = (toolName: string, input: Record<string, unknown>, cwd: string) => PermissionRequest[];
|
|
10
|
+
/** Marks a bash request target that no command-specific rule can match: only a `*` rule decides it. */
|
|
11
|
+
export declare const UNPARSED_BASH_PREFIX = "(unparsed) ";
|
|
10
12
|
/** The `eval` class a cell carries on its own, used when its tool-owned parser names anything narrower. */
|
|
11
13
|
export declare function fallbackEvalPermissionRequest(): PermissionRequest;
|
|
12
14
|
/**
|
|
@@ -2,6 +2,7 @@ import { dirname, resolve } from "node:path";
|
|
|
2
2
|
import { realpathWithoutOpen } from "../../../../utils/paths.js";
|
|
3
3
|
import { extractPatchedPaths } from "../gpt-apply-patch/index.js";
|
|
4
4
|
import { BashArity } from "../permission-system/arity.js";
|
|
5
|
+
import { analyzeBashCommand, bestEffortCommandLines } from "../permission-system/bash-command-segments.js";
|
|
5
6
|
import { extractExternalPaths, isExternalPath, toParentDirectoryPattern, } from "../permission-system/external-dir.js";
|
|
6
7
|
import { setApprovedMonitorParent } from "../terminal/monitor-permission.js";
|
|
7
8
|
import { urlOriginAlias, widerAlwaysScope } from "./always-scope.js";
|
|
@@ -73,6 +74,48 @@ function withExternalDirectoryRequests(requests, paths, cwd, scope) {
|
|
|
73
74
|
},
|
|
74
75
|
];
|
|
75
76
|
}
|
|
77
|
+
const uniq = (values) => [...new Set(values)];
|
|
78
|
+
/**
|
|
79
|
+
* The targets an "Allow always" answer may store. Stored rules are matched as globs, so a target holding
|
|
80
|
+
* its own `*` or `?` would be remembered as a wildcard that matches other commands; such a target is
|
|
81
|
+
* allowed once and never stored. Request patterns stay raw, so existing rules match exactly as before.
|
|
82
|
+
*/
|
|
83
|
+
const rememberable = (targets) => targets.filter((target) => !/[*?]/.test(target));
|
|
84
|
+
/** Marks a bash request target that no command-specific rule can match: only a `*` rule decides it. */
|
|
85
|
+
export const UNPARSED_BASH_PREFIX = "(unparsed) ";
|
|
86
|
+
/**
|
|
87
|
+
* The `bash` requests for one command. Every simple command it runs is decided, so the call is as
|
|
88
|
+
* strict as its strictest command: one pattern per command (its arity prefix), all of which must be
|
|
89
|
+
* allowed, and "Allow always" stores exactly those prefixes. A command the lexer cannot parse is one
|
|
90
|
+
* target only a `*` rule (a preset, a blanket setting) can decide, so no grant for one command can
|
|
91
|
+
* allow it; its plain words are still checked against deny rules.
|
|
92
|
+
*/
|
|
93
|
+
function bashCommandRequests(command) {
|
|
94
|
+
const analysis = analyzeBashCommand(command);
|
|
95
|
+
if (analysis.kind === "unparsed") {
|
|
96
|
+
const target = `${UNPARSED_BASH_PREFIX}${command}`;
|
|
97
|
+
const candidates = uniq(bestEffortCommandLines(command)
|
|
98
|
+
.map((words) => BashArity.prefix(words).join(" "))
|
|
99
|
+
.filter(Boolean));
|
|
100
|
+
// The deny-only check runs first, so a denied call is refused before anyone is asked.
|
|
101
|
+
return [
|
|
102
|
+
...(candidates.length === 0
|
|
103
|
+
? []
|
|
104
|
+
: [{ permission: "bash", patterns: candidates, always: [], autoApproveAsk: true }]),
|
|
105
|
+
{ permission: "bash", patterns: [target], always: rememberable([target]) },
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
const prefixes = uniq(analysis.segments.map((words) => BashArity.prefix([...words]).join(" ")).filter(Boolean));
|
|
109
|
+
if (prefixes.length === 0)
|
|
110
|
+
return [{ permission: "bash", patterns: [command], always: rememberable([command]) }];
|
|
111
|
+
return [
|
|
112
|
+
{
|
|
113
|
+
permission: "bash",
|
|
114
|
+
patterns: prefixes,
|
|
115
|
+
always: rememberable(prefixes).flatMap((prefix) => [prefix, `${prefix} *`]),
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
}
|
|
76
119
|
/** The `eval` class a cell carries on its own, used when its tool-owned parser names anything narrower. */
|
|
77
120
|
export function fallbackEvalPermissionRequest() {
|
|
78
121
|
return { permission: "eval", patterns: ["*"], always: ["*"] };
|
|
@@ -135,16 +178,7 @@ export function createBuiltinParserRegistry() {
|
|
|
135
178
|
if (!command) {
|
|
136
179
|
return [fallbackPermissionRequest("bash")];
|
|
137
180
|
}
|
|
138
|
-
const
|
|
139
|
-
const prefix = BashArity.prefix(tokens).join(" ");
|
|
140
|
-
const always = prefix ? [prefix, `${prefix} *`] : ["*"];
|
|
141
|
-
const requests = [
|
|
142
|
-
{
|
|
143
|
-
permission: "bash",
|
|
144
|
-
patterns: [prefix || command],
|
|
145
|
-
always,
|
|
146
|
-
},
|
|
147
|
-
];
|
|
181
|
+
const requests = bashCommandRequests(command);
|
|
148
182
|
const externalPaths = extractExternalPaths(command, cwd);
|
|
149
183
|
if (externalPaths.length > 0) {
|
|
150
184
|
requests.push({
|
|
@@ -58,8 +58,9 @@ export function bundleSinks(pi, state) {
|
|
|
58
58
|
pi.events?.emit(WAKE_SOURCE_STATE_EVENT, {
|
|
59
59
|
source: "terminal-monitors",
|
|
60
60
|
activeCount: snapshot.length,
|
|
61
|
+
// The stable "mon_" id: runtime ids churn on restore, and item ids feed the custody signature.
|
|
61
62
|
monitors: snapshot.map((entry) => ({
|
|
62
|
-
id: entry.id,
|
|
63
|
+
id: entry.monitorId ?? entry.id,
|
|
63
64
|
description: entry.description,
|
|
64
65
|
startedAtMs: entry.startedAtMs,
|
|
65
66
|
})),
|
|
@@ -8,9 +8,18 @@ export declare const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application defaul
|
|
|
8
8
|
* gcloud tooling too, so the lane is selectable but never outranks a provider the
|
|
9
9
|
* user configured, and it reports nothing while the chain is absent — the failure
|
|
10
10
|
* belongs at selection time, not at the first request.
|
|
11
|
+
*
|
|
12
|
+
* The target project is resolved here so it rides the ambient auth result into
|
|
13
|
+
* the request env: process env first, then the sibling google-vertex profile,
|
|
14
|
+
* which shares this ADC chain and already names the project the user entered at
|
|
15
|
+
* its login. With neither source the lane stays available and the request-time
|
|
16
|
+
* ADC fallbacks (quota project, discovered project) decide, so a missing project
|
|
17
|
+
* remains a first-request failure with the actionable error, not a hidden lane.
|
|
11
18
|
*/
|
|
12
19
|
export declare function resolveVertexModelGardenAmbient(input: {
|
|
13
20
|
ctx: AuthContext;
|
|
14
21
|
signal: AbortSignal;
|
|
22
|
+
/** Read-only env of another provider's stored credential; routing metadata only, never keys. */
|
|
23
|
+
storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
|
|
15
24
|
}): Promise<AuthResult | undefined>;
|
|
16
25
|
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -7,6 +7,13 @@ export const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application default creden
|
|
|
7
7
|
* gcloud tooling too, so the lane is selectable but never outranks a provider the
|
|
8
8
|
* user configured, and it reports nothing while the chain is absent — the failure
|
|
9
9
|
* belongs at selection time, not at the first request.
|
|
10
|
+
*
|
|
11
|
+
* The target project is resolved here so it rides the ambient auth result into
|
|
12
|
+
* the request env: process env first, then the sibling google-vertex profile,
|
|
13
|
+
* which shares this ADC chain and already names the project the user entered at
|
|
14
|
+
* its login. With neither source the lane stays available and the request-time
|
|
15
|
+
* ADC fallbacks (quota project, discovered project) decide, so a missing project
|
|
16
|
+
* remains a first-request failure with the actionable error, not a hidden lane.
|
|
10
17
|
*/
|
|
11
18
|
export async function resolveVertexModelGardenAmbient(input) {
|
|
12
19
|
input.signal.throwIfAborted();
|
|
@@ -14,6 +21,15 @@ export async function resolveVertexModelGardenAmbient(input) {
|
|
|
14
21
|
input.signal.throwIfAborted();
|
|
15
22
|
if (!(await input.ctx.fileExists(path)))
|
|
16
23
|
return undefined;
|
|
17
|
-
|
|
24
|
+
input.signal.throwIfAborted();
|
|
25
|
+
const project = (await input.ctx.env("GOOGLE_CLOUD_PROJECT")) ??
|
|
26
|
+
(await input.ctx.env("GCLOUD_PROJECT")) ??
|
|
27
|
+
(await input.storedProviderEnv?.("google-vertex"))?.GOOGLE_CLOUD_PROJECT;
|
|
28
|
+
return {
|
|
29
|
+
auth: {},
|
|
30
|
+
...(project ? { env: { GOOGLE_CLOUD_PROJECT: project } } : {}),
|
|
31
|
+
source: VERTEX_MODEL_GARDEN_ADC_SOURCE,
|
|
32
|
+
ambient: true,
|
|
33
|
+
};
|
|
18
34
|
}
|
|
19
35
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import type { ProviderModule } from "./shared.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Catalog GA flash alias: it tracks the current stable flash model, so the default
|
|
4
|
+
* cannot age into a retired generation (gemini-2.5-flash 404s for new accounts).
|
|
5
|
+
* An entry-level `model` still overrides it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_MODEL = "gemini-flash-latest";
|
|
2
8
|
export declare const googleProvider: ProviderModule;
|
|
3
9
|
//# sourceMappingURL=google.d.ts.map
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { providerUrl } from "../provider-endpoints.js";
|
|
2
2
|
import { appendDomainFilters, collect, contentHeaders, getArray, getNumber, getObject, getString, result, withConfigHeaders, } from "./shared.js";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Catalog GA flash alias: it tracks the current stable flash model, so the default
|
|
5
|
+
* cannot age into a retired generation (gemini-2.5-flash 404s for new accounts).
|
|
6
|
+
* An entry-level `model` still overrides it.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_MODEL = "gemini-flash-latest";
|
|
4
9
|
function generateContentUrl(config) {
|
|
5
10
|
const root = providerUrl(config).replace(/\/+$/, "");
|
|
6
11
|
if (root.endsWith(":generateContent"))
|
|
@@ -2369,6 +2369,8 @@ export interface ProviderConfig {
|
|
|
2369
2369
|
resolve(input: {
|
|
2370
2370
|
ctx: AuthContext;
|
|
2371
2371
|
signal: AbortSignal;
|
|
2372
|
+
/** Read-only env of another provider's stored credential; routing metadata only, never keys. */
|
|
2373
|
+
storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
|
|
2372
2374
|
}): Promise<AuthResult | undefined>;
|
|
2373
2375
|
};
|
|
2374
2376
|
/** OAuth provider for /login support. The `id` is set automatically from the provider name. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChildLifecycleReport, SessionLifecycleState } from "./session-lifecycle-types.ts";
|
|
1
|
+
import type { ChildLifecycleReport, LifecycleWaits, SessionLifecycleState } from "./session-lifecycle-types.ts";
|
|
2
2
|
import type { SessionEntry } from "./session-manager.ts";
|
|
3
3
|
export interface ChildLifecycleStore {
|
|
4
4
|
readonly entries: readonly SessionEntry[];
|
|
@@ -15,4 +15,6 @@ export declare class LifecycleChildren {
|
|
|
15
15
|
private accept;
|
|
16
16
|
}
|
|
17
17
|
export declare function readLifecycleState(value: unknown): SessionLifecycleState | undefined;
|
|
18
|
+
/** The one reader of a durable or reported `waitingOn`; named detail never invalidates the counts. */
|
|
19
|
+
export declare function readWaits(value: unknown): LifecycleWaits | undefined;
|
|
18
20
|
//# sourceMappingURL=lifecycle-children.d.ts.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readHumanWait } from "./lifecycle-attention.js";
|
|
2
|
+
import { readWaitItems } from "./lifecycle-wait-items.js";
|
|
1
3
|
import { isRecord } from "./work-custody-record.js";
|
|
2
4
|
export class LifecycleChildren {
|
|
3
5
|
constructor(store) {
|
|
@@ -60,6 +62,80 @@ export function readLifecycleState(value) {
|
|
|
60
62
|
return undefined;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
/** The one reader of a durable or reported `waitingOn`; named detail never invalidates the counts. */
|
|
66
|
+
export function readWaits(value) {
|
|
67
|
+
if (!isRecord(value) || typeof value.children !== "number")
|
|
68
|
+
return undefined;
|
|
69
|
+
const background = [];
|
|
70
|
+
if (Array.isArray(value.background)) {
|
|
71
|
+
for (const source of value.background) {
|
|
72
|
+
if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
|
|
73
|
+
continue;
|
|
74
|
+
background.push({
|
|
75
|
+
source: source.source,
|
|
76
|
+
activeCount: source.activeCount,
|
|
77
|
+
...readWaitItems(source.items, source.omittedItems),
|
|
78
|
+
...(typeof source.retryAtMs === "number" ? { retryAtMs: source.retryAtMs } : {}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const human = Array.isArray(value.human)
|
|
83
|
+
? value.human.flatMap((request) => {
|
|
84
|
+
const wait = readHumanWait(request);
|
|
85
|
+
return wait ? [wait] : [];
|
|
86
|
+
})
|
|
87
|
+
: [];
|
|
88
|
+
const childSources = [];
|
|
89
|
+
if (Array.isArray(value.childSources))
|
|
90
|
+
for (const source of value.childSources) {
|
|
91
|
+
if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
|
|
92
|
+
continue;
|
|
93
|
+
childSources.push({
|
|
94
|
+
source: source.source,
|
|
95
|
+
activeCount: source.activeCount,
|
|
96
|
+
...readWaitItems(source.items, source.omittedItems),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const reports = [];
|
|
100
|
+
if (Array.isArray(value.childReports))
|
|
101
|
+
for (const report of value.childReports) {
|
|
102
|
+
if (!isRecord(report))
|
|
103
|
+
continue;
|
|
104
|
+
const state = readLifecycleState(report.state);
|
|
105
|
+
if (!state ||
|
|
106
|
+
typeof report.taskId !== "string" ||
|
|
107
|
+
typeof report.childSessionId !== "string" ||
|
|
108
|
+
typeof report.runEpoch !== "number" ||
|
|
109
|
+
!Number.isSafeInteger(report.runEpoch) ||
|
|
110
|
+
report.runEpoch < 0)
|
|
111
|
+
continue;
|
|
112
|
+
reports.push({
|
|
113
|
+
taskId: report.taskId,
|
|
114
|
+
childSessionId: report.childSessionId,
|
|
115
|
+
runEpoch: report.runEpoch,
|
|
116
|
+
state,
|
|
117
|
+
...(typeof report.label === "string" ? { label: report.label } : {}),
|
|
118
|
+
...(typeof report.since === "string" && Number.isFinite(Date.parse(report.since))
|
|
119
|
+
? { since: report.since }
|
|
120
|
+
: {}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
reports.sort((a, b) => (a.taskId < b.taskId ? -1 : a.taskId > b.taskId ? 1 : 0));
|
|
124
|
+
const childReportsOmitted = Math.max(0, reports.length - 32) +
|
|
125
|
+
(typeof value.childReportsOmitted === "number" &&
|
|
126
|
+
Number.isSafeInteger(value.childReportsOmitted) &&
|
|
127
|
+
value.childReportsOmitted > 0
|
|
128
|
+
? value.childReportsOmitted
|
|
129
|
+
: 0);
|
|
130
|
+
return {
|
|
131
|
+
children: value.children,
|
|
132
|
+
background,
|
|
133
|
+
human,
|
|
134
|
+
...(childSources.length ? { childSources } : {}),
|
|
135
|
+
...(reports.length ? { childReports: reports.slice(0, 32) } : {}),
|
|
136
|
+
...(childReportsOmitted ? { childReportsOmitted } : {}),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
63
139
|
function readChildReport(value) {
|
|
64
140
|
if (!isRecord(value))
|
|
65
141
|
return undefined;
|
|
@@ -75,27 +151,15 @@ function readChildReport(value) {
|
|
|
75
151
|
value.generation < 0)
|
|
76
152
|
return undefined;
|
|
77
153
|
const terminal = readTerminal(value.terminal);
|
|
78
|
-
|
|
79
|
-
if (isRecord(value.waitingOn) && typeof value.waitingOn.children === "number") {
|
|
80
|
-
const background = [];
|
|
81
|
-
if (Array.isArray(value.waitingOn.background))
|
|
82
|
-
for (const item of value.waitingOn.background) {
|
|
83
|
-
if (!isRecord(item) || typeof item.source !== "string" || typeof item.activeCount !== "number")
|
|
84
|
-
continue;
|
|
85
|
-
background.push({
|
|
86
|
-
source: item.source,
|
|
87
|
-
activeCount: item.activeCount,
|
|
88
|
-
...(typeof item.retryAtMs === "number" ? { retryAtMs: item.retryAtMs } : {}),
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
waitingOn = { children: value.waitingOn.children, background, human: [] };
|
|
92
|
-
}
|
|
154
|
+
const waitingOn = readWaits(value.waitingOn);
|
|
93
155
|
return {
|
|
94
156
|
taskId: value.taskId,
|
|
95
157
|
childSessionId: value.childSessionId,
|
|
96
158
|
runEpoch: value.runEpoch,
|
|
97
159
|
generation: value.generation,
|
|
98
160
|
state,
|
|
161
|
+
...(typeof value.label === "string" ? { label: value.label } : {}),
|
|
162
|
+
...(typeof value.since === "string" && Number.isFinite(Date.parse(value.since)) ? { since: value.since } : {}),
|
|
99
163
|
...(waitingOn ? { waitingOn } : {}),
|
|
100
164
|
...(terminal === undefined ? {} : { terminal }),
|
|
101
165
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readHumanWait } from "./lifecycle-attention.js";
|
|
2
|
-
import { readLifecycleState } from "./lifecycle-children.js";
|
|
2
|
+
import { readLifecycleState, readWaits } from "./lifecycle-children.js";
|
|
3
3
|
import { readLastStop } from "./lifecycle-stop.js";
|
|
4
4
|
import { isRecord } from "./work-custody-record.js";
|
|
5
5
|
/** Restore the wire snapshot and its private high-water marks from owned JSONL. */
|
|
@@ -97,29 +97,6 @@ function readTurnEnd(value) {
|
|
|
97
97
|
return undefined;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
function readWaits(value) {
|
|
101
|
-
if (!isRecord(value) || typeof value.children !== "number")
|
|
102
|
-
return undefined;
|
|
103
|
-
const background = [];
|
|
104
|
-
if (Array.isArray(value.background)) {
|
|
105
|
-
for (const source of value.background) {
|
|
106
|
-
if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
|
|
107
|
-
continue;
|
|
108
|
-
background.push({
|
|
109
|
-
source: source.source,
|
|
110
|
-
activeCount: source.activeCount,
|
|
111
|
-
...(typeof source.retryAtMs === "number" ? { retryAtMs: source.retryAtMs } : {}),
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
const human = Array.isArray(value.human)
|
|
116
|
-
? value.human.flatMap((request) => {
|
|
117
|
-
const wait = readHumanWait(request);
|
|
118
|
-
return wait ? [wait] : [];
|
|
119
|
-
})
|
|
120
|
-
: [];
|
|
121
|
-
return { children: value.children, background, human };
|
|
122
|
-
}
|
|
123
100
|
function readHolds(value) {
|
|
124
101
|
if (!Array.isArray(value))
|
|
125
102
|
return undefined;
|
|
@@ -9,6 +9,7 @@ import { lifecycleHistory } from "./lifecycle-history.js";
|
|
|
9
9
|
import { bindLifecycleHumanInput } from "./lifecycle-human-input.js";
|
|
10
10
|
import { readLifecycleRuntimeFacts } from "./lifecycle-runtime-facts.js";
|
|
11
11
|
import { goalGuardAfter } from "./lifecycle-stop.js";
|
|
12
|
+
import { wakeSourceItems } from "./lifecycle-wait-items.js";
|
|
12
13
|
import { SessionLifecycleController } from "./session-lifecycle.js";
|
|
13
14
|
import { isRecord } from "./work-custody-record.js";
|
|
14
15
|
/** Attaches durable lifecycle to the real session event/admission boundaries. */
|
|
@@ -310,7 +311,7 @@ export class LifecycleSessionBinding {
|
|
|
310
311
|
return;
|
|
311
312
|
if (!Number.isFinite(data.activeCount))
|
|
312
313
|
return;
|
|
313
|
-
this.controller.obligations.syncSource(data.source, data.kind === "children" ? "children" : "background", data.activeCount);
|
|
314
|
+
this.controller.obligations.syncSource(data.source, data.kind === "children" ? "children" : "background", data.activeCount, wakeSourceItems(data));
|
|
314
315
|
}
|
|
315
316
|
dispose() {
|
|
316
317
|
this.disposed = true;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { WakeSourceStateItem } from "./extensions/builtin/monitor-state-event.ts";
|
|
2
|
+
import type { LifecycleWaitItem } from "./session-lifecycle-types.ts";
|
|
3
|
+
export interface WaitSourceItems {
|
|
4
|
+
readonly items?: readonly WakeSourceStateItem[];
|
|
5
|
+
readonly omittedItems?: number;
|
|
6
|
+
}
|
|
7
|
+
/** Optional producer detail never determines custody. Lists are snapshots, bounded independently of activeCount. */
|
|
8
|
+
export declare function normalizeWaitItems(value: unknown, omitted?: unknown): WaitSourceItems;
|
|
9
|
+
/** The one rule for a wake_source_state producer's item list: `items` when set, else the legacy `monitors`. */
|
|
10
|
+
export declare function wakeSourceItems(data: object): unknown;
|
|
11
|
+
export declare function waitItemSignature(detail: WaitSourceItems): string;
|
|
12
|
+
export declare function projectWaitItems(detail: WaitSourceItems): {
|
|
13
|
+
readonly items?: readonly LifecycleWaitItem[];
|
|
14
|
+
readonly omittedItems?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function readWaitItems(value: unknown, omitted?: unknown): ReturnType<typeof projectWaitItems>;
|
|
17
|
+
//# sourceMappingURL=lifecycle-wait-items.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Optional producer detail never determines custody. Lists are snapshots, bounded independently of activeCount. */
|
|
2
|
+
export function normalizeWaitItems(value, omitted) {
|
|
3
|
+
const byId = new Map();
|
|
4
|
+
if (Array.isArray(value)) {
|
|
5
|
+
for (const entry of value) {
|
|
6
|
+
if (typeof entry !== "object" || entry === null || !("id" in entry))
|
|
7
|
+
continue;
|
|
8
|
+
if (typeof entry.id !== "string" || entry.id.trim().length === 0)
|
|
9
|
+
continue;
|
|
10
|
+
const item = {
|
|
11
|
+
id: entry.id,
|
|
12
|
+
...("description" in entry && typeof entry.description === "string"
|
|
13
|
+
? { description: entry.description }
|
|
14
|
+
: {}),
|
|
15
|
+
...("startedAtMs" in entry &&
|
|
16
|
+
typeof entry.startedAtMs === "number" &&
|
|
17
|
+
Number.isFinite(entry.startedAtMs) &&
|
|
18
|
+
Math.abs(entry.startedAtMs) <= 8.64e15
|
|
19
|
+
? { startedAtMs: entry.startedAtMs }
|
|
20
|
+
: {}),
|
|
21
|
+
};
|
|
22
|
+
const previous = byId.get(item.id);
|
|
23
|
+
if (!previous || JSON.stringify(item) < JSON.stringify(previous))
|
|
24
|
+
byId.set(item.id, item);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const items = [...byId.values()].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
28
|
+
const omittedItems = Math.max(0, items.length - 32) +
|
|
29
|
+
(typeof omitted === "number" && Number.isSafeInteger(omitted) && omitted > 0 ? omitted : 0);
|
|
30
|
+
return {
|
|
31
|
+
...(items.length ? { items: items.slice(0, 32) } : {}),
|
|
32
|
+
...(omittedItems ? { omittedItems } : {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** The one rule for a wake_source_state producer's item list: `items` when set, else the legacy `monitors`. */
|
|
36
|
+
export function wakeSourceItems(data) {
|
|
37
|
+
return ("items" in data ? data.items : undefined) ?? ("monitors" in data ? data.monitors : undefined);
|
|
38
|
+
}
|
|
39
|
+
export function waitItemSignature(detail) {
|
|
40
|
+
return JSON.stringify([detail.items?.map((item) => [item.id, item.description]), detail.omittedItems]);
|
|
41
|
+
}
|
|
42
|
+
export function projectWaitItems(detail) {
|
|
43
|
+
return {
|
|
44
|
+
...(detail.items
|
|
45
|
+
? {
|
|
46
|
+
items: detail.items.map((item) => ({
|
|
47
|
+
id: item.id,
|
|
48
|
+
...(item.description === undefined ? {} : { label: item.description }),
|
|
49
|
+
...(item.startedAtMs === undefined ? {} : { startedAt: new Date(item.startedAtMs).toISOString() }),
|
|
50
|
+
})),
|
|
51
|
+
}
|
|
52
|
+
: {}),
|
|
53
|
+
...(detail.omittedItems ? { omittedItems: detail.omittedItems } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function readWaitItems(value, omitted) {
|
|
57
|
+
const items = Array.isArray(value)
|
|
58
|
+
? value.map((item) => {
|
|
59
|
+
if (typeof item !== "object" || item === null)
|
|
60
|
+
return item;
|
|
61
|
+
return {
|
|
62
|
+
...("id" in item ? { id: item.id } : {}),
|
|
63
|
+
...("label" in item ? { description: item.label } : {}),
|
|
64
|
+
...("startedAt" in item && typeof item.startedAt === "string"
|
|
65
|
+
? { startedAtMs: Date.parse(item.startedAt) }
|
|
66
|
+
: {}),
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
: undefined;
|
|
70
|
+
return projectWaitItems(normalizeWaitItems(items, omitted));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=lifecycle-wait-items.js.map
|
|
@@ -245,7 +245,12 @@ export class ModelRuntime {
|
|
|
245
245
|
return base;
|
|
246
246
|
}
|
|
247
247
|
try {
|
|
248
|
-
|
|
248
|
+
// The reader runs only inside ambient auth resolution; composition itself stays credential-free.
|
|
249
|
+
const storedProviderEnv = async (sourceId) => {
|
|
250
|
+
const credential = await this.credentials.read(sourceId);
|
|
251
|
+
return credential?.type === "api_key" && credential.env ? { ...credential.env } : undefined;
|
|
252
|
+
};
|
|
253
|
+
const provider = composeModelProvider(providerId, base, this.config, extension, { storedProviderEnv });
|
|
249
254
|
this.compositionErrors.delete(providerId);
|
|
250
255
|
return provider;
|
|
251
256
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type ApiKeyAuth, type AuthContext, type AuthResult, type ModelAuth, type Provider, type ProviderHeaders } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { ConfigValue } from "@earendil-works/pi-ai/utils/config-reference";
|
|
3
3
|
import type { ModelsJsonProvider } from "./model-config.ts";
|
|
4
|
+
/** Reads another provider's stored credential env: routing metadata only, never keys. */
|
|
5
|
+
export type StoredProviderEnvReader = (providerId: string) => Promise<Record<string, string> | undefined>;
|
|
4
6
|
interface AmbientAuthExtensionInput {
|
|
5
7
|
name?: string;
|
|
6
8
|
resolve(input: {
|
|
7
9
|
ctx: AuthContext;
|
|
8
10
|
signal: AbortSignal;
|
|
11
|
+
storedProviderEnv?: StoredProviderEnvReader;
|
|
9
12
|
}): Promise<AuthResult | undefined>;
|
|
10
13
|
}
|
|
11
14
|
interface ProviderAuthExtensionInput {
|
|
@@ -19,7 +22,9 @@ interface ProviderAuthExtensionInput {
|
|
|
19
22
|
oauth?: unknown;
|
|
20
23
|
ambientAuth?: AmbientAuthExtensionInput;
|
|
21
24
|
}
|
|
22
|
-
export declare function composeApiKeyAuth(providerId: string, base: Provider | undefined, config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined
|
|
25
|
+
export declare function composeApiKeyAuth(providerId: string, base: Provider | undefined, config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined, options?: {
|
|
26
|
+
storedProviderEnv?: StoredProviderEnvReader;
|
|
27
|
+
}): ApiKeyAuth | undefined;
|
|
23
28
|
export declare function configuredApiKey(config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): ConfigValue | undefined;
|
|
24
29
|
export declare function configuredHeaders(config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): Record<string, ConfigValue> | undefined;
|
|
25
30
|
export declare function withConfiguredAuth(auth: ModelAuth, headers: ProviderHeaders | undefined, authHeader: boolean): ModelAuth;
|
|
@@ -2,7 +2,7 @@ import { hasCredentialHeaders, } from "@earendil-works/pi-ai";
|
|
|
2
2
|
import { assertConfigReferenceAuthority } from "./config-reference-resolver.js";
|
|
3
3
|
import { checkConfiguredHeaderAuth, headerAuthResolutionSource } from "./provider-header-auth.js";
|
|
4
4
|
import { getConfigValueEnvVarNames, isCommandConfigValue, resolveConfigValueOrThrow, resolveHeadersOrThrow, } from "./resolve-config-value.js";
|
|
5
|
-
export function composeApiKeyAuth(providerId, base, config, extension) {
|
|
5
|
+
export function composeApiKeyAuth(providerId, base, config, extension, options) {
|
|
6
6
|
const inherited = base?.auth.apiKey;
|
|
7
7
|
const rawKey = configuredApiKey(config, extension);
|
|
8
8
|
const oauth = extension?.oauth ?? base?.auth.oauth;
|
|
@@ -15,7 +15,7 @@ export function composeApiKeyAuth(providerId, base, config, extension) {
|
|
|
15
15
|
// explicitly configured key, credential headers, or a base provider still
|
|
16
16
|
// win, and a resolution marked ambient never outranks a configured
|
|
17
17
|
// provider in automatic default selection (senpi#2327).
|
|
18
|
-
return ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader);
|
|
18
|
+
return ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader, options?.storedProviderEnv);
|
|
19
19
|
}
|
|
20
20
|
if (!inherited && rawKey === undefined && !headerSource && oauth) {
|
|
21
21
|
// An OAuth provider with no key, no credential headers and no base normally
|
|
@@ -119,16 +119,23 @@ function ambientOnlyAuth(providerId, oauth, rawHeaders, headerSource, authHeader
|
|
|
119
119
|
* is the only source — and `Models.checkAuth` resolves this auth, so the
|
|
120
120
|
* `ambient` marker reaches the provider's auth status.
|
|
121
121
|
*/
|
|
122
|
-
function ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader) {
|
|
122
|
+
function ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader, storedProviderEnv) {
|
|
123
123
|
const resolve = async (input) => {
|
|
124
|
-
const result = await ambient.resolve({
|
|
124
|
+
const result = await ambient.resolve({
|
|
125
|
+
ctx: input.ctx,
|
|
126
|
+
signal: input.signal,
|
|
127
|
+
...(storedProviderEnv ? { storedProviderEnv } : {}),
|
|
128
|
+
});
|
|
125
129
|
if (!result)
|
|
126
130
|
return undefined;
|
|
127
131
|
const explicitEnv = { ...(input.credential?.env ?? {}), ...(result.env ?? {}) };
|
|
128
132
|
const headerEnv = await configContextEnv(Object.values(rawHeaders ?? {}), input.ctx, explicitEnv);
|
|
129
133
|
const headers = await resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, headerEnv);
|
|
134
|
+
// Stored-then-env (helpers.ts invariant): the provider's own stored env wins over ambient-resolved env.
|
|
135
|
+
const env = result.env || input.credential?.env ? { ...(result.env ?? {}), ...(input.credential?.env ?? {}) } : undefined;
|
|
130
136
|
return {
|
|
131
137
|
...result,
|
|
138
|
+
...(env ? { env } : {}),
|
|
132
139
|
auth: withConfiguredAuth(result.auth, headers, authHeader),
|
|
133
140
|
source: result.source ?? headerSource,
|
|
134
141
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AnyModel, type Api, type AssistantMessageEventStream, type AuthCheck, type AuthContext, type AuthResult, type ClassifierApi, type ImageApi, type Model, type OAuthCredential, type OAuthCredentials, type OAuthLoginCallbacks, type Provider, type ProviderClassifier, type ProviderImages, type RefreshModelsContext, type SimpleStreamOptions, type TranscriptContext } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { RetryPolicyProfile } from "@earendil-works/pi-ai/utils/retry-profile/types";
|
|
3
3
|
import type { ModelConfig, ModelsJsonProvider } from "./model-config.ts";
|
|
4
|
+
import { type StoredProviderEnvReader } from "./provider-api-key-auth.ts";
|
|
4
5
|
import type { HeaderAuthStatusSource } from "./provider-header-auth.ts";
|
|
5
6
|
import { clearConfigValueCache } from "./resolve-config-value.ts";
|
|
6
7
|
export interface ExtensionOAuthConfig {
|
|
@@ -120,6 +121,8 @@ export interface ProviderAmbientAuth {
|
|
|
120
121
|
resolve(input: {
|
|
121
122
|
ctx: AuthContext;
|
|
122
123
|
signal: AbortSignal;
|
|
124
|
+
/** Read-only env of another provider's stored credential; routing metadata only, never keys. */
|
|
125
|
+
storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
|
|
123
126
|
}): Promise<AuthResult | undefined>;
|
|
124
127
|
}
|
|
125
128
|
export type AuthStatus = {
|
|
@@ -133,7 +136,11 @@ export { configuredRequestAuthStatus, resolveCompatibilityRequestHeaders, resolv
|
|
|
133
136
|
export declare const clearApiKeyCache: typeof clearConfigValueCache;
|
|
134
137
|
export declare function validateExtensionProvider(providerId: string, base: Provider | undefined, modelsConfig: ModelsJsonProvider | undefined, extension: ProviderConfigInput): void;
|
|
135
138
|
/** Compose built-in, models.json, and extension layers without reading credentials. */
|
|
136
|
-
export declare function composeModelProvider(providerId: string, base: Provider | undefined, modelConfig: ModelConfig, extension: ProviderConfigInput | undefined
|
|
139
|
+
export declare function composeModelProvider(providerId: string, base: Provider | undefined, modelConfig: ModelConfig, extension: ProviderConfigInput | undefined,
|
|
140
|
+
/** Deferred ambient reads; the reader runs during auth resolution, never at composition. */
|
|
141
|
+
options?: {
|
|
142
|
+
storedProviderEnv?: StoredProviderEnvReader;
|
|
143
|
+
}): Provider;
|
|
137
144
|
/**
|
|
138
145
|
* Request shape a compatibility provider needs beside its credential. Headers are NOT
|
|
139
146
|
* part of it: a configured header value can be a `!command`, and resolving one requires
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getApiProvider, getCurrentTools, getProtocol, getToolCallFormat, isModelType, lazyStream, transformContext, wrapStreamWithToolCallMiddleware, } from "@earendil-works/pi-ai";
|
|
2
2
|
import { classifierErrorResult, imageErrorResult } from "@earendil-works/pi-ai/utils/model-operations";
|
|
3
|
-
import { composeApiKeyAuth, configuredHeaders, withConfiguredAuth } from "./provider-api-key-auth.js";
|
|
3
|
+
import { composeApiKeyAuth, configuredHeaders, withConfiguredAuth, } from "./provider-api-key-auth.js";
|
|
4
4
|
import { clearConfigValueCache, resolveHeadersOrThrow } from "./resolve-config-value.js";
|
|
5
5
|
export { configuredRequestAuthStatus, resolveCompatibilityRequestHeaders, resolveConfiguredModelHeaders, } from "./provider-request-auth.js";
|
|
6
6
|
export const clearApiKeyCache = clearConfigValueCache;
|
|
@@ -286,7 +286,9 @@ export function validateExtensionProvider(providerId, base, modelsConfig, extens
|
|
|
286
286
|
applyExtension(providerId, applyModelsJson(providerId, getAllProviderModels(base), modelsConfig, extension), extension, new Set((modelsConfig?.models ?? []).map((definition) => definition.id)));
|
|
287
287
|
}
|
|
288
288
|
/** Compose built-in, models.json, and extension layers without reading credentials. */
|
|
289
|
-
export function composeModelProvider(providerId, base, modelConfig, extension
|
|
289
|
+
export function composeModelProvider(providerId, base, modelConfig, extension,
|
|
290
|
+
/** Deferred ambient reads; the reader runs during auth resolution, never at composition. */
|
|
291
|
+
options) {
|
|
290
292
|
const config = modelConfig.getProvider(providerId);
|
|
291
293
|
let extensionOAuthCredential;
|
|
292
294
|
let refreshedExtensionModels;
|
|
@@ -309,7 +311,9 @@ export function composeModelProvider(providerId, base, modelConfig, extension) {
|
|
|
309
311
|
};
|
|
310
312
|
// Validate eagerly so registration/reload reports structural errors immediately.
|
|
311
313
|
getAllModels();
|
|
312
|
-
const apiKey = composeApiKeyAuth(providerId, base, config, extension
|
|
314
|
+
const apiKey = composeApiKeyAuth(providerId, base, config, extension, {
|
|
315
|
+
storedProviderEnv: options?.storedProviderEnv,
|
|
316
|
+
});
|
|
313
317
|
const oauth = composeOAuthAuth(providerId, base, config, extension);
|
|
314
318
|
if (!apiKey && !oauth)
|
|
315
319
|
throw new Error(`Provider ${providerId}: no authentication method configured.`);
|
package/dist/core/sdk.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import { Agent, setDefaultStreamFn } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { Agent, createInternalAgentChannel, setDefaultStreamFn, } from "@earendil-works/pi-agent-core";
|
|
3
3
|
import { modelsAreEqual, streamSimple } from "@earendil-works/pi-ai/compat";
|
|
4
4
|
import { getAgentDir } from "../config.js";
|
|
5
5
|
import { resolvePath } from "../utils/paths.js";
|
|
@@ -283,7 +283,9 @@ export async function createAgentSession(options = {}) {
|
|
|
283
283
|
model: model.id,
|
|
284
284
|
});
|
|
285
285
|
};
|
|
286
|
+
const internalChannel = createInternalAgentChannel();
|
|
286
287
|
agent = new Agent({
|
|
288
|
+
internalChannel,
|
|
287
289
|
initialState: {
|
|
288
290
|
systemPrompt: "",
|
|
289
291
|
model,
|
|
@@ -382,6 +384,7 @@ export async function createAgentSession(options = {}) {
|
|
|
382
384
|
: options.sessionStartEvent;
|
|
383
385
|
const session = new AgentSession({
|
|
384
386
|
agent,
|
|
387
|
+
internalChannel,
|
|
385
388
|
serviceTier: options.serviceTier,
|
|
386
389
|
sessionManager,
|
|
387
390
|
settingsManager,
|