@open-agent-toolkit/cli 0.2.51 → 0.2.53
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/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/bootstrap.md +6 -2
- package/assets/docs/cli-utilities/tool-packs.md +87 -33
- package/assets/docs/provider-sync/commands.md +30 -2
- package/assets/docs/provider-sync/config.md +19 -0
- package/assets/docs/provider-sync/manifest-and-drift.md +37 -0
- package/assets/docs/provider-sync/providers.md +69 -2
- package/assets/docs/provider-sync/scope-and-surface.md +44 -0
- package/assets/docs/reference/cli-reference.md +1 -0
- package/assets/docs/reference/oat-directory-structure.md +11 -4
- package/assets/docs/workflows/projects/evidence-layers.md +110 -1
- package/assets/docs/workflows/projects/implementation-execution.md +13 -0
- package/assets/docs/workflows/projects/orchestration-model.md +18 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-dispatch-subagents/SKILL.md +57 -1
- package/assets/skills/oat-dispatch-subagents/references/record-schema.md +77 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
- package/assets/skills/oat-project-dispatch-subagents/SKILL.md +24 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +11 -0
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-plan-writing/SKILL.md +12 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-review-provide/SKILL.md +12 -1
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +12 -1
- package/dist/agents/canonical/index.d.ts +2 -0
- package/dist/agents/canonical/index.d.ts.map +1 -1
- package/dist/agents/canonical/index.js +1 -0
- package/dist/agents/canonical/resolve.d.ts +45 -0
- package/dist/agents/canonical/resolve.d.ts.map +1 -0
- package/dist/agents/canonical/resolve.js +175 -0
- package/dist/commands/decision/agents-guidance.d.ts +2 -2
- package/dist/commands/decision/agents-guidance.d.ts.map +1 -1
- package/dist/commands/decision/agents-guidance.js +1 -4
- package/dist/commands/decision/index.d.ts.map +1 -1
- package/dist/commands/decision/index.js +25 -6
- package/dist/commands/docs/init/index.d.ts +7 -1
- package/dist/commands/docs/init/index.d.ts.map +1 -1
- package/dist/commands/docs/init/index.js +53 -20
- package/dist/commands/doctor/index.d.ts +8 -2
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +157 -46
- package/dist/commands/init/index.d.ts +8 -3
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +66 -28
- package/dist/commands/init/tools/index.d.ts +12 -12
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +430 -99
- package/dist/commands/init/tools/install-state.d.ts +2 -0
- package/dist/commands/init/tools/install-state.d.ts.map +1 -1
- package/dist/commands/init/tools/install-state.js +11 -0
- package/dist/commands/init/tools/project-guidance.d.ts +49 -0
- package/dist/commands/init/tools/project-guidance.d.ts.map +1 -0
- package/dist/commands/init/tools/project-guidance.js +144 -0
- package/dist/commands/init/tools/workflows/index.d.ts +7 -0
- package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
- package/dist/commands/init/tools/workflows/index.js +160 -7
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +28 -3
- package/dist/commands/pjm/init.d.ts +5 -0
- package/dist/commands/pjm/init.d.ts.map +1 -1
- package/dist/commands/pjm/init.js +19 -3
- package/dist/commands/project/dispatch/index.d.ts +10 -0
- package/dist/commands/project/dispatch/index.d.ts.map +1 -0
- package/dist/commands/project/dispatch/index.js +137 -0
- package/dist/commands/project/dispatch/record.d.ts +91 -0
- package/dist/commands/project/dispatch/record.d.ts.map +1 -0
- package/dist/commands/project/dispatch/record.js +402 -0
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/providers/inspect/inspect.d.ts +8 -1
- package/dist/commands/providers/inspect/inspect.d.ts.map +1 -1
- package/dist/commands/providers/inspect/inspect.js +146 -26
- package/dist/commands/providers/list/list.d.ts +8 -1
- package/dist/commands/providers/list/list.d.ts.map +1 -1
- package/dist/commands/providers/list/list.js +139 -23
- package/dist/commands/providers/providers.types.d.ts +25 -1
- package/dist/commands/providers/providers.types.d.ts.map +1 -1
- package/dist/commands/providers/set/index.d.ts +9 -1
- package/dist/commands/providers/set/index.d.ts.map +1 -1
- package/dist/commands/providers/set/index.js +43 -33
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +11 -0
- package/dist/commands/shared/agents-md.d.ts +42 -14
- package/dist/commands/shared/agents-md.d.ts.map +1 -1
- package/dist/commands/shared/agents-md.js +364 -70
- package/dist/commands/status/index.d.ts +8 -3
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +149 -37
- package/dist/commands/sync/apply.d.ts.map +1 -1
- package/dist/commands/sync/apply.js +220 -29
- package/dist/commands/sync/dry-run.d.ts.map +1 -1
- package/dist/commands/sync/dry-run.js +30 -6
- package/dist/commands/sync/index.d.ts +17 -2
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +108 -43
- package/dist/commands/sync/sync.types.d.ts +39 -2
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.d.ts +5 -1
- package/dist/commands/sync/sync.utils.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.js +73 -0
- package/dist/commands/tools/info/info-tool.d.ts +2 -0
- package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
- package/dist/commands/tools/info/info-tool.js +34 -12
- package/dist/commands/tools/install/index.d.ts.map +1 -1
- package/dist/commands/tools/install/index.js +19 -3
- package/dist/commands/tools/list/list-tools.d.ts +2 -0
- package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
- package/dist/commands/tools/list/list-tools.js +36 -7
- package/dist/commands/tools/remove/index.d.ts.map +1 -1
- package/dist/commands/tools/remove/index.js +150 -21
- package/dist/commands/tools/remove/remove-tools.d.ts +20 -0
- package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
- package/dist/commands/tools/remove/remove-tools.js +122 -1
- package/dist/commands/tools/shared/format-pack-inventory.d.ts +19 -0
- package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/format-pack-inventory.js +109 -0
- package/dist/commands/tools/shared/pack-evidence.d.ts +66 -0
- package/dist/commands/tools/shared/pack-evidence.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-evidence.js +132 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts +1 -0
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts +44 -0
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-lifecycle-outcome.js +91 -0
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +74 -4
- package/dist/commands/tools/update/update-tools.d.ts +5 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/commands/tools/update/update-tools.js +64 -2
- package/dist/config/oat-config.d.ts +5 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +17 -5
- package/dist/config/user-sync-config.d.ts +1 -0
- package/dist/config/user-sync-config.d.ts.map +1 -1
- package/dist/config/user-sync-config.js +8 -0
- package/dist/drift/detector.d.ts +2 -2
- package/dist/drift/detector.d.ts.map +1 -1
- package/dist/drift/detector.js +18 -0
- package/dist/drift/strays.d.ts.map +1 -1
- package/dist/drift/strays.js +5 -0
- package/dist/engine/collection-sync.d.ts +14 -0
- package/dist/engine/collection-sync.d.ts.map +1 -0
- package/dist/engine/collection-sync.js +282 -0
- package/dist/engine/compute-plan.d.ts +8 -1
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +303 -12
- package/dist/engine/engine.types.d.ts +61 -0
- package/dist/engine/engine.types.d.ts.map +1 -1
- package/dist/engine/execute-plan.d.ts +22 -2
- package/dist/engine/execute-plan.d.ts.map +1 -1
- package/dist/engine/execute-plan.js +459 -27
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/engine/provider-path-safety.d.ts +1 -0
- package/dist/engine/provider-path-safety.d.ts.map +1 -1
- package/dist/engine/provider-path-safety.js +15 -0
- package/dist/engine/scanner.d.ts +9 -2
- package/dist/engine/scanner.d.ts.map +1 -1
- package/dist/engine/scanner.js +58 -4
- package/dist/fs/io.d.ts +67 -0
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +536 -3
- package/dist/manifest/index.d.ts +2 -2
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +1 -1
- package/dist/manifest/manager.d.ts +2 -2
- package/dist/manifest/manager.d.ts.map +1 -1
- package/dist/manifest/manager.js +20 -3
- package/dist/manifest/manifest.types.d.ts +704 -13
- package/dist/manifest/manifest.types.d.ts.map +1 -1
- package/dist/manifest/manifest.types.js +131 -15
- package/dist/providers/codex/codec/sync-extension.d.ts +1 -1
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +48 -17
- package/dist/providers/cursor/codec/sync-extension.d.ts +1 -1
- package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/cursor/codec/sync-extension.js +52 -23
- package/dist/providers/identity/absolute-paths.d.ts +68 -0
- package/dist/providers/identity/absolute-paths.d.ts.map +1 -0
- package/dist/providers/identity/absolute-paths.js +144 -0
- package/dist/providers/identity/claude-runtime-observation.d.ts +105 -0
- package/dist/providers/identity/claude-runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts +40 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts.map +1 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.js +146 -0
- package/dist/providers/identity/claude-runtime-observation.js +229 -0
- package/dist/providers/identity/codex-runtime-observation.d.ts +75 -0
- package/dist/providers/identity/codex-runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts +37 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts.map +1 -0
- package/dist/providers/identity/codex-runtime-observation.fixtures.js +539 -0
- package/dist/providers/identity/codex-runtime-observation.js +255 -0
- package/dist/providers/identity/generic-dispatch-record.d.ts +313 -0
- package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -0
- package/dist/providers/identity/generic-dispatch-record.js +539 -0
- package/dist/providers/identity/oat-dispatch-record.d.ts +1964 -0
- package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -0
- package/dist/providers/identity/oat-dispatch-record.js +691 -0
- package/dist/providers/identity/runtime-observation.d.ts +100 -0
- package/dist/providers/identity/runtime-observation.d.ts.map +1 -0
- package/dist/providers/identity/runtime-observation.js +169 -0
- package/dist/providers/shared/index.d.ts +2 -0
- package/dist/providers/shared/index.d.ts.map +1 -1
- package/dist/providers/shared/index.js +1 -0
- package/dist/providers/shared/materialization-extension.d.ts +12 -0
- package/dist/providers/shared/materialization-extension.d.ts.map +1 -1
- package/dist/providers/shared/registry.d.ts +69 -0
- package/dist/providers/shared/registry.d.ts.map +1 -0
- package/dist/providers/shared/registry.js +252 -0
- package/dist/providers/shared/restart-adviser.d.ts +26 -0
- package/dist/providers/shared/restart-adviser.d.ts.map +1 -0
- package/dist/providers/shared/restart-adviser.js +96 -0
- package/dist/shared/types.d.ts +4 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { GenericDispatchRecord } from './generic-dispatch-record.js';
|
|
3
|
+
import { type RuntimeObservation } from './oat-dispatch-record.js';
|
|
4
|
+
/**
|
|
5
|
+
* Envelope shape only. Size is deliberately *not* enforced here.
|
|
6
|
+
*
|
|
7
|
+
* A shape, provider, or content violation is a caller error and fails closed.
|
|
8
|
+
* A size violation is not: the observation layer is optional and
|
|
9
|
+
* non-authoritative, so refusing an oversized transcript by throwing would
|
|
10
|
+
* destroy the mandatory record write over an optional attachment. Size is
|
|
11
|
+
* checked separately and degrades to `not-reported`.
|
|
12
|
+
*/
|
|
13
|
+
declare const runtimeObservationEnvelopeSchema: z.ZodObject<{
|
|
14
|
+
provider: z.ZodString;
|
|
15
|
+
observedAt: z.ZodString;
|
|
16
|
+
entries: z.ZodArray<z.ZodUnknown, "many">;
|
|
17
|
+
}, "strict", z.ZodTypeAny, {
|
|
18
|
+
provider: string;
|
|
19
|
+
observedAt: string;
|
|
20
|
+
entries: unknown[];
|
|
21
|
+
}, {
|
|
22
|
+
provider: string;
|
|
23
|
+
observedAt: string;
|
|
24
|
+
entries: unknown[];
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* True when the envelope is too large to project. Degrading rather than fatal.
|
|
28
|
+
*
|
|
29
|
+
* Bounded by entry count alone, and deliberately not by serialized size. An
|
|
30
|
+
* earlier revision measured bytes with `JSON.stringify`, which did the very
|
|
31
|
+
* unbounded work the bound exists to prevent — serializing tens of megabytes to
|
|
32
|
+
* conclude they were too big — and, worse, *read every conversation field on
|
|
33
|
+
* the way*. That put the one read of `content` in the codebase inside the
|
|
34
|
+
* bounding step, while the parsers themselves touched nothing.
|
|
35
|
+
*
|
|
36
|
+
* Entry count is O(1) and reads nothing. It is a sufficient bound because
|
|
37
|
+
* projection work is O(entries x a fixed allowlist of scalar keys) and each
|
|
38
|
+
* value read is length-capped at 256 characters by the shared identifier
|
|
39
|
+
* validator, so a single entry cannot carry unbounded cost no matter how large
|
|
40
|
+
* its unread fields are.
|
|
41
|
+
*/
|
|
42
|
+
export declare function runtimeObservationEnvelopeExceedsBounds(entries: readonly unknown[]): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The closed, neutral set of facts an observation can carry.
|
|
45
|
+
*
|
|
46
|
+
* Every key is owned by this module and checked against the sensitive-key
|
|
47
|
+
* classifier. Provider field names never appear here, so a provider renaming a
|
|
48
|
+
* field cannot change what the boundary sees.
|
|
49
|
+
*/
|
|
50
|
+
export interface ObservedRuntimeFacts {
|
|
51
|
+
lineage?: string | null;
|
|
52
|
+
role?: string | null;
|
|
53
|
+
model?: string | null;
|
|
54
|
+
effort?: string | null;
|
|
55
|
+
serviceTier?: string | null;
|
|
56
|
+
/** Provider-declared OAT request correlation, when the provider states one. */
|
|
57
|
+
correlation?: string | null;
|
|
58
|
+
}
|
|
59
|
+
export declare const OBSERVED_RUNTIME_FACT_KEYS: readonly ['lineage', 'role', 'model', 'effort', 'serviceTier', 'correlation'];
|
|
60
|
+
export type RuntimeObservationEnvelope = z.infer<typeof runtimeObservationEnvelopeSchema>;
|
|
61
|
+
/**
|
|
62
|
+
* Project raw provider output down to the neutral fact set.
|
|
63
|
+
*
|
|
64
|
+
* Callers may hand over an unmodified rollout or transcript. All provider
|
|
65
|
+
* parsing happens inside the provider module; only the neutral facts come back,
|
|
66
|
+
* so nothing of the source shape — including its key names — reaches the
|
|
67
|
+
* boundary. Returns `null` for an unsupported provider, an over-bound envelope,
|
|
68
|
+
* or output that yields no facts.
|
|
69
|
+
*/
|
|
70
|
+
export declare function projectRuntimeObservationFacts(provider: string, entries: readonly unknown[]): ObservedRuntimeFacts | null;
|
|
71
|
+
/**
|
|
72
|
+
* Why an observation degraded. `null` reason means facts were produced.
|
|
73
|
+
*/
|
|
74
|
+
export interface ProjectedRuntimeObservation {
|
|
75
|
+
facts: ObservedRuntimeFacts | null;
|
|
76
|
+
reason: string | null;
|
|
77
|
+
}
|
|
78
|
+
export declare function projectRuntimeObservation(provider: string, entries: readonly unknown[]): ProjectedRuntimeObservation;
|
|
79
|
+
/**
|
|
80
|
+
* Build the observation from already-projected neutral facts.
|
|
81
|
+
*
|
|
82
|
+
* `source` names the path that produced the evidence and is supplied by the
|
|
83
|
+
* caller of this function, never by the dispatch caller.
|
|
84
|
+
*/
|
|
85
|
+
export declare function observationFromFacts(input: {
|
|
86
|
+
record: GenericDispatchRecord;
|
|
87
|
+
provider: string;
|
|
88
|
+
source: string;
|
|
89
|
+
observedAt: string;
|
|
90
|
+
facts: ObservedRuntimeFacts | null;
|
|
91
|
+
}): RuntimeObservation;
|
|
92
|
+
export declare function providerSupportsRuntimeObservation(provider: string): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Validate the envelope shape. Provider metadata entries stay opaque here: the
|
|
95
|
+
* parsers read only allowlisted metadata fields out of them, and only the
|
|
96
|
+
* extracted identifiers ever reach the strict observation schema.
|
|
97
|
+
*/
|
|
98
|
+
export declare function parseRuntimeObservationEnvelope(value: unknown): RuntimeObservationEnvelope;
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=runtime-observation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-observation.d.ts","sourceRoot":"","sources":["../../../src/providers/identity/runtime-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AA0C/B;;;;;;;;GAQG;AACH,QAAA,MAAM,gCAAgC;;;;;;;;;;;;EAM3B,CAAC;AAEZ;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,SAAS,OAAO,EAAE,GAC1B,OAAO,CAET;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,0BAA0B,YACrC,SAAS,EACT,MAAM,EACN,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,CACL,CAAC;AAEX,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,OAAO,EAAE,GAC1B,oBAAoB,GAAG,IAAI,CAE7B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,OAAO,EAAE,GAC1B,2BAA2B,CAsC7B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,MAAM,EAAE,qBAAqB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACpC,GAAG,kBAAkB,CAerB;AAED,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,GACb,0BAA0B,CAE5B"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { observeClaudeRuntimeFacts } from './claude-runtime-observation.js';
|
|
3
|
+
import { observeCodexRuntimeFacts } from './codex-runtime-observation.js';
|
|
4
|
+
import { buildRuntimeObservation, configuredInvocationForObservation, } from './oat-dispatch-record.js';
|
|
5
|
+
/**
|
|
6
|
+
* Cross-provider runtime observation normalizer.
|
|
7
|
+
*
|
|
8
|
+
* This is the one place a provider's post-launch metadata is turned into the
|
|
9
|
+
* record's optional observation layer. It reads the immutable configured
|
|
10
|
+
* invocation only to compare against it: launch, fallback, and every configured
|
|
11
|
+
* control are untouched, and a mismatch or absence is evidence rather than
|
|
12
|
+
* authorization.
|
|
13
|
+
*
|
|
14
|
+
* Observation is capability-gated. A provider with no metadata channel — Cursor
|
|
15
|
+
* today — stays explicitly `not-reported` instead of having requested arguments
|
|
16
|
+
* or materialized pins copied into observed state.
|
|
17
|
+
*
|
|
18
|
+
* ## Why projection emits a neutral shape
|
|
19
|
+
*
|
|
20
|
+
* The projection deliberately does **not** mirror the provider's own entry
|
|
21
|
+
* shape. An earlier revision emitted provider-shaped entries, which carried
|
|
22
|
+
* `sessionId` and a synthesized `message` into the output; both classify
|
|
23
|
+
* sensitive under the Phase 6 key classifier, so every real Claude transcript
|
|
24
|
+
* was refused at the durable-write boundary and the whole record write aborted.
|
|
25
|
+
* Mirroring a source shape means inheriting its key names, and a provider is
|
|
26
|
+
* free to name a field anything.
|
|
27
|
+
*
|
|
28
|
+
* Projection therefore emits {@link ObservedRuntimeFacts}: a flat, closed set
|
|
29
|
+
* of purpose-built keys owned by this module. Provider-specific parsing happens
|
|
30
|
+
* entirely inside the provider modules and nothing of the source shape escapes
|
|
31
|
+
* them, so no upstream rename can reintroduce a collision. The keys are checked
|
|
32
|
+
* against the classifier by `neutral projection keys are not sensitive` in this
|
|
33
|
+
* module's tests.
|
|
34
|
+
*/
|
|
35
|
+
const OBSERVING_PROVIDERS = new Set(['codex', 'claude']);
|
|
36
|
+
/**
|
|
37
|
+
* Bound on how much provider metadata one observation may be derived from. The
|
|
38
|
+
* entries are never persisted, but an unbounded input would still be unbounded
|
|
39
|
+
* work at a durable-write boundary.
|
|
40
|
+
*/
|
|
41
|
+
const MAX_ENVELOPE_ENTRIES = 5000;
|
|
42
|
+
/**
|
|
43
|
+
* Envelope shape only. Size is deliberately *not* enforced here.
|
|
44
|
+
*
|
|
45
|
+
* A shape, provider, or content violation is a caller error and fails closed.
|
|
46
|
+
* A size violation is not: the observation layer is optional and
|
|
47
|
+
* non-authoritative, so refusing an oversized transcript by throwing would
|
|
48
|
+
* destroy the mandatory record write over an optional attachment. Size is
|
|
49
|
+
* checked separately and degrades to `not-reported`.
|
|
50
|
+
*/
|
|
51
|
+
const runtimeObservationEnvelopeSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
provider: z.string().min(1).max(256),
|
|
54
|
+
observedAt: z.string().datetime(),
|
|
55
|
+
entries: z.array(z.unknown()),
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
/**
|
|
59
|
+
* True when the envelope is too large to project. Degrading rather than fatal.
|
|
60
|
+
*
|
|
61
|
+
* Bounded by entry count alone, and deliberately not by serialized size. An
|
|
62
|
+
* earlier revision measured bytes with `JSON.stringify`, which did the very
|
|
63
|
+
* unbounded work the bound exists to prevent — serializing tens of megabytes to
|
|
64
|
+
* conclude they were too big — and, worse, *read every conversation field on
|
|
65
|
+
* the way*. That put the one read of `content` in the codebase inside the
|
|
66
|
+
* bounding step, while the parsers themselves touched nothing.
|
|
67
|
+
*
|
|
68
|
+
* Entry count is O(1) and reads nothing. It is a sufficient bound because
|
|
69
|
+
* projection work is O(entries x a fixed allowlist of scalar keys) and each
|
|
70
|
+
* value read is length-capped at 256 characters by the shared identifier
|
|
71
|
+
* validator, so a single entry cannot carry unbounded cost no matter how large
|
|
72
|
+
* its unread fields are.
|
|
73
|
+
*/
|
|
74
|
+
export function runtimeObservationEnvelopeExceedsBounds(entries) {
|
|
75
|
+
return entries.length > MAX_ENVELOPE_ENTRIES;
|
|
76
|
+
}
|
|
77
|
+
export const OBSERVED_RUNTIME_FACT_KEYS = [
|
|
78
|
+
'lineage',
|
|
79
|
+
'role',
|
|
80
|
+
'model',
|
|
81
|
+
'effort',
|
|
82
|
+
'serviceTier',
|
|
83
|
+
'correlation',
|
|
84
|
+
];
|
|
85
|
+
/**
|
|
86
|
+
* Project raw provider output down to the neutral fact set.
|
|
87
|
+
*
|
|
88
|
+
* Callers may hand over an unmodified rollout or transcript. All provider
|
|
89
|
+
* parsing happens inside the provider module; only the neutral facts come back,
|
|
90
|
+
* so nothing of the source shape — including its key names — reaches the
|
|
91
|
+
* boundary. Returns `null` for an unsupported provider, an over-bound envelope,
|
|
92
|
+
* or output that yields no facts.
|
|
93
|
+
*/
|
|
94
|
+
export function projectRuntimeObservationFacts(provider, entries) {
|
|
95
|
+
return projectRuntimeObservation(provider, entries).facts;
|
|
96
|
+
}
|
|
97
|
+
export function projectRuntimeObservation(provider, entries) {
|
|
98
|
+
if (!providerSupportsRuntimeObservation(provider)) {
|
|
99
|
+
return {
|
|
100
|
+
facts: null,
|
|
101
|
+
reason: `provider ${provider} exposes no runtime observation channel`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(entries)) {
|
|
105
|
+
return { facts: null, reason: 'observation metadata was not a list' };
|
|
106
|
+
}
|
|
107
|
+
if (runtimeObservationEnvelopeExceedsBounds(entries)) {
|
|
108
|
+
return {
|
|
109
|
+
facts: null,
|
|
110
|
+
reason: `observation metadata is too large to project (${entries.length} entries, limit ${MAX_ENVELOPE_ENTRIES})`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const facts = provider === 'codex'
|
|
114
|
+
? observeCodexRuntimeFacts(entries)
|
|
115
|
+
: observeClaudeRuntimeFacts(entries);
|
|
116
|
+
if (facts === null) {
|
|
117
|
+
return {
|
|
118
|
+
facts: null,
|
|
119
|
+
reason: 'observation metadata reported no identity facts',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// Re-emit through the owned key list so only declared facts can escape.
|
|
123
|
+
const projected = {};
|
|
124
|
+
for (const key of OBSERVED_RUNTIME_FACT_KEYS) {
|
|
125
|
+
const value = facts[key];
|
|
126
|
+
if (typeof value === 'string' && value !== '')
|
|
127
|
+
projected[key] = value;
|
|
128
|
+
}
|
|
129
|
+
return Object.keys(projected).length > 0
|
|
130
|
+
? { facts: projected, reason: null }
|
|
131
|
+
: {
|
|
132
|
+
facts: null,
|
|
133
|
+
reason: 'observation metadata reported no identity facts',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Build the observation from already-projected neutral facts.
|
|
138
|
+
*
|
|
139
|
+
* `source` names the path that produced the evidence and is supplied by the
|
|
140
|
+
* caller of this function, never by the dispatch caller.
|
|
141
|
+
*/
|
|
142
|
+
export function observationFromFacts(input) {
|
|
143
|
+
if (input.facts === null)
|
|
144
|
+
return { status: 'not-reported' };
|
|
145
|
+
const { correlation, lineage, ...axes } = input.facts;
|
|
146
|
+
// Declared-correlation guard, on the path that actually writes records.
|
|
147
|
+
// A session that names a different request is not evidence about this one.
|
|
148
|
+
if (correlation != null && correlation !== input.record.request_id) {
|
|
149
|
+
return { status: 'not-reported' };
|
|
150
|
+
}
|
|
151
|
+
return buildRuntimeObservation({
|
|
152
|
+
provider: input.provider,
|
|
153
|
+
source: input.source,
|
|
154
|
+
observedAt: input.observedAt,
|
|
155
|
+
metadata: { childLineage: lineage, ...axes },
|
|
156
|
+
configured: configuredInvocationForObservation(input.record),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
export function providerSupportsRuntimeObservation(provider) {
|
|
160
|
+
return OBSERVING_PROVIDERS.has(provider);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate the envelope shape. Provider metadata entries stay opaque here: the
|
|
164
|
+
* parsers read only allowlisted metadata fields out of them, and only the
|
|
165
|
+
* extracted identifiers ever reach the strict observation schema.
|
|
166
|
+
*/
|
|
167
|
+
export function parseRuntimeObservationEnvelope(value) {
|
|
168
|
+
return runtimeObservationEnvelopeSchema.parse(value);
|
|
169
|
+
}
|
|
@@ -5,4 +5,6 @@ export type { ProviderAgentCodec, ProviderAgentRecord, } from './agent-codec.typ
|
|
|
5
5
|
export { exportMarkdownAgentRecord, importMarkdownAgentRecord, } from './markdown-agent-codec.js';
|
|
6
6
|
export type { MaterializationAction, MaterializationApplyResult, MaterializationContext, MaterializationExtension, MaterializationOperation, MaterializationPlan, MaterializationPlanSummary, MaterializationWriteOperation, } from './materialization-extension.js';
|
|
7
7
|
export { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from './materialization-extension.js';
|
|
8
|
+
export type { ManagedContentKind, ProviderActivationEvidence, ProviderActivationSource, ProviderCapabilitySupport, ProviderCatalogRefreshPolicy, ProviderContentCapability, ProviderProjectionMode, ProviderRegistration, ProviderScopeContext, } from './registry.js';
|
|
9
|
+
export { getProviderRegistrations, recomputeProviderScopeContext, resolveProviderScopeContext, validateProviderRegistrations, } from './registry.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,YAAY,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { getActiveAdapters, getConfigAwareAdapters, getSyncMappings, } from './adapter.utils.js';
|
|
2
2
|
export { exportMarkdownAgentRecord, importMarkdownAgentRecord, } from './markdown-agent-codec.js';
|
|
3
3
|
export { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from './materialization-extension.js';
|
|
4
|
+
export { getProviderRegistrations, recomputeProviderScopeContext, resolveProviderScopeContext, validateProviderRegistrations, } from './registry.js';
|
|
@@ -22,6 +22,18 @@ export interface MaterializationApplyResult {
|
|
|
22
22
|
applied: number;
|
|
23
23
|
failed: number;
|
|
24
24
|
skipped: number;
|
|
25
|
+
/** Additive per-operation evidence; optional for legacy extensions. */
|
|
26
|
+
operations?: MaterializationOperationResult[];
|
|
27
|
+
}
|
|
28
|
+
export type MaterializationOperationStatus = 'changed' | 'current' | 'missing' | 'failed' | 'unsupported' | 'unknown';
|
|
29
|
+
export interface MaterializationOperationResult {
|
|
30
|
+
provider: string;
|
|
31
|
+
target: string;
|
|
32
|
+
path: string;
|
|
33
|
+
entryName?: string;
|
|
34
|
+
action: MaterializationAction;
|
|
35
|
+
status: MaterializationOperationStatus;
|
|
36
|
+
failure?: string;
|
|
25
37
|
}
|
|
26
38
|
export interface MaterializationContext<TOptions = undefined> {
|
|
27
39
|
scopeRoot: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialization-extension.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/materialization-extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5E,MAAM,WAAW,wBAAwB,CACvC,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM;IAE/B,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,6BAA6B,CAC5C,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM,CAC/B,SAAQ,wBAAwB,CAAC,SAAS,EAAE,OAAO,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB,CAClC,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/B,SAAS,GAAG,OAAO;IAEnB,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,6BAA6B,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;IAChE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"materialization-extension.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/materialization-extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5E,MAAM,WAAW,wBAAwB,CACvC,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM;IAE/B,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,6BAA6B,CAC5C,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM,CAC/B,SAAQ,wBAAwB,CAAC,SAAS,EAAE,OAAO,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB,CAClC,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/B,SAAS,GAAG,OAAO;IAEnB,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,6BAA6B,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;IAChE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,UAAU,CAAC,EAAE,8BAA8B,EAAE,CAAC;CAC/C;AAED,MAAM,MAAM,8BAA8B,GACtC,SAAS,GACT,SAAS,GACT,SAAS,GACT,QAAQ,GACR,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,8BAA8B,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB,CAAC,QAAQ,GAAG,SAAS;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,cAAc,EAAE,CAAC;IACnC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB,CACvC,KAAK,SAAS,mBAAmB,GAAG,mBAAmB,EACvD,QAAQ,SAAS,sBAAsB,CAAC,OAAO,CAAC,GAC9C,sBAAsB,CAAC,OAAO,CAAC;IAEjC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5B,WAAW,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/C,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,KAAK,GACV,OAAO,CAAC,0BAA0B,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAE5E;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,mBAAmB,GACxB,0BAA0B,CAa5B;AAED,wBAAgB,2BAA2B,CACzC,SAAS,SAAS,MAAM,EACxB,OAAO,SAAS,MAAM,EAEtB,IAAI,EAAE,mBAAmB,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,GACrD,wBAAwB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAShD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { SyncConfig } from '../../config/sync-config.js';
|
|
2
|
+
import type { ConcreteScope, ContentType } from '../../shared/types.js';
|
|
3
|
+
import type { ProviderAdapter } from './adapter.types.js';
|
|
4
|
+
import type { MaterializationExtension } from './materialization-extension.js';
|
|
5
|
+
export type ProviderProjectionMode = 'native-read' | 'entry-sync' | 'materialization-extension' | 'unsupported';
|
|
6
|
+
export type ManagedContentKind = ContentType | 'directory';
|
|
7
|
+
export type ProviderCapabilitySupport = 'supported' | 'unsupported' | 'unknown';
|
|
8
|
+
export type ProviderCatalogRefreshPolicy = {
|
|
9
|
+
state: 'live' | 'manual-refresh' | 'restart-required';
|
|
10
|
+
provenance: {
|
|
11
|
+
kind: 'official-contract' | 'validated-local-behavior' | 'repository-decision';
|
|
12
|
+
reference: string;
|
|
13
|
+
verifiedAt: string;
|
|
14
|
+
providerVersion?: string;
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
state: 'unknown';
|
|
18
|
+
reason: string;
|
|
19
|
+
};
|
|
20
|
+
export interface ProviderContentCapability {
|
|
21
|
+
scope: ConcreteScope;
|
|
22
|
+
contentKind: ManagedContentKind;
|
|
23
|
+
support: ProviderCapabilitySupport;
|
|
24
|
+
projectionModes: readonly ProviderProjectionMode[];
|
|
25
|
+
nativeRoleSurface: boolean;
|
|
26
|
+
collectionAlias: 'supported' | 'unsupported';
|
|
27
|
+
catalogRefresh: ProviderCatalogRefreshPolicy;
|
|
28
|
+
unsupportedReason?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ProviderRegistration {
|
|
31
|
+
adapter: ProviderAdapter;
|
|
32
|
+
extensions: readonly MaterializationExtension[];
|
|
33
|
+
capabilities: readonly ProviderContentCapability[];
|
|
34
|
+
}
|
|
35
|
+
export type ProviderActivationSource = 'config-enabled' | 'config-disabled' | 'detected-unset' | 'undetected-unset';
|
|
36
|
+
export interface ProviderActivationEvidence {
|
|
37
|
+
provider: string;
|
|
38
|
+
state: 'active' | 'inactive';
|
|
39
|
+
source: ProviderActivationSource;
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ProviderScopeContext {
|
|
43
|
+
scope: ConcreteScope;
|
|
44
|
+
configSource: string;
|
|
45
|
+
activeProviders: readonly string[];
|
|
46
|
+
detectedProviders: readonly string[];
|
|
47
|
+
mismatches: {
|
|
48
|
+
detectedUnset: readonly string[];
|
|
49
|
+
detectedDisabled: readonly string[];
|
|
50
|
+
};
|
|
51
|
+
activation: readonly ProviderActivationEvidence[];
|
|
52
|
+
registrations: readonly ProviderRegistration[];
|
|
53
|
+
}
|
|
54
|
+
export declare function resolveCatalogRefreshPolicy(supported: boolean, providerPolicy?: ProviderCatalogRefreshPolicy): ProviderCatalogRefreshPolicy;
|
|
55
|
+
export type UserAgentMaterializationCoverage = 'none' | 'bundled' | 'all';
|
|
56
|
+
export declare function userAgentMaterializationCoverage(input: {
|
|
57
|
+
registrations: readonly ProviderRegistration[];
|
|
58
|
+
activeProviders: readonly string[];
|
|
59
|
+
}): UserAgentMaterializationCoverage;
|
|
60
|
+
export declare function validateProviderRegistrations(registrations: readonly ProviderRegistration[]): void;
|
|
61
|
+
export declare function getProviderRegistrations(): readonly ProviderRegistration[];
|
|
62
|
+
export declare function resolveProviderScopeContext(input: {
|
|
63
|
+
scope: ConcreteScope;
|
|
64
|
+
scopeRoot: string;
|
|
65
|
+
config: SyncConfig;
|
|
66
|
+
registrations?: readonly ProviderRegistration[];
|
|
67
|
+
}): Promise<ProviderScopeContext>;
|
|
68
|
+
export declare function recomputeProviderScopeContext(snapshot: Pick<ProviderScopeContext, 'scope' | 'configSource' | 'detectedProviders' | 'registrations'>, config: SyncConfig): ProviderScopeContext;
|
|
69
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { claudeAdapter } from '../claude/index.js';
|
|
3
|
+
import { codexAdapter } from '../codex/index.js';
|
|
4
|
+
import { codexMaterializationExtension } from '../codex/codec/sync-extension.js';
|
|
5
|
+
import { copilotAdapter } from '../copilot/index.js';
|
|
6
|
+
import { cursorAdapter } from '../cursor/index.js';
|
|
7
|
+
import { cursorMaterializationExtension } from '../cursor/codec/sync-extension.js';
|
|
8
|
+
import { geminiAdapter } from '../gemini/index.js';
|
|
9
|
+
const CONTENT_KINDS = [
|
|
10
|
+
'skill',
|
|
11
|
+
'agent',
|
|
12
|
+
'rule',
|
|
13
|
+
'directory',
|
|
14
|
+
];
|
|
15
|
+
const SCOPES = ['project', 'user'];
|
|
16
|
+
const UNKNOWN_REFRESH = {
|
|
17
|
+
state: 'unknown',
|
|
18
|
+
reason: 'No sourced provider-version refresh contract is registered',
|
|
19
|
+
};
|
|
20
|
+
const CONSERVATIVE_NEW_SESSION_REFRESH = {
|
|
21
|
+
state: 'restart-required',
|
|
22
|
+
provenance: {
|
|
23
|
+
kind: 'repository-decision',
|
|
24
|
+
reference: '.oat/projects/shared/tool-pack-scope-provider-truthfulness/implementation.md#hill-decision-conservative-new-session-advice',
|
|
25
|
+
verifiedAt: '2026-08-31',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const REFRESH_PROVENANCE_KINDS = new Set([
|
|
29
|
+
'official-contract',
|
|
30
|
+
'validated-local-behavior',
|
|
31
|
+
'repository-decision',
|
|
32
|
+
]);
|
|
33
|
+
export function resolveCatalogRefreshPolicy(supported, providerPolicy) {
|
|
34
|
+
if (!supported)
|
|
35
|
+
return UNKNOWN_REFRESH;
|
|
36
|
+
return providerPolicy ?? CONSERVATIVE_NEW_SESSION_REFRESH;
|
|
37
|
+
}
|
|
38
|
+
function hasValidRefreshProvenance(policy) {
|
|
39
|
+
if (policy.state === 'unknown')
|
|
40
|
+
return true;
|
|
41
|
+
const provenance = policy.provenance;
|
|
42
|
+
if (!provenance || !REFRESH_PROVENANCE_KINDS.has(provenance.kind)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (typeof provenance.reference !== 'string' ||
|
|
46
|
+
provenance.reference.trim().length === 0) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (provenance.providerVersion !== undefined &&
|
|
50
|
+
(typeof provenance.providerVersion !== 'string' ||
|
|
51
|
+
provenance.providerVersion.trim().length === 0)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (typeof provenance.verifiedAt !== 'string' ||
|
|
55
|
+
!/^\d{4}-\d{2}-\d{2}$/.test(provenance.verifiedAt)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const date = new Date(`${provenance.verifiedAt}T00:00:00.000Z`);
|
|
59
|
+
return (!Number.isNaN(date.getTime()) &&
|
|
60
|
+
date.toISOString().slice(0, 10) === provenance.verifiedAt);
|
|
61
|
+
}
|
|
62
|
+
export function userAgentMaterializationCoverage(input) {
|
|
63
|
+
const active = new Set(input.activeProviders);
|
|
64
|
+
let coverage = 'none';
|
|
65
|
+
for (const registration of input.registrations) {
|
|
66
|
+
if (!active.has(registration.adapter.name))
|
|
67
|
+
continue;
|
|
68
|
+
const capability = registration.capabilities.find(({ scope, contentKind }) => scope === 'user' && contentKind === 'agent');
|
|
69
|
+
if (capability?.support !== 'supported')
|
|
70
|
+
continue;
|
|
71
|
+
if (capability.projectionModes.includes('entry-sync'))
|
|
72
|
+
return 'all';
|
|
73
|
+
if (capability.projectionModes.includes('materialization-extension')) {
|
|
74
|
+
coverage = 'bundled';
|
|
75
|
+
}
|
|
76
|
+
else if (capability.projectionModes.includes('native-read')) {
|
|
77
|
+
return 'all';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return coverage;
|
|
81
|
+
}
|
|
82
|
+
function capabilitiesFor(adapter, extensionContentKinds = [], refreshPolicies = {}) {
|
|
83
|
+
return SCOPES.flatMap((scope) => {
|
|
84
|
+
const mappings = scope === 'project' ? adapter.projectMappings : adapter.userMappings;
|
|
85
|
+
return CONTENT_KINDS.map((contentKind) => {
|
|
86
|
+
const mapping = mappings.find(({ contentType }) => contentType === contentKind);
|
|
87
|
+
const hasExtension = extensionContentKinds.includes(contentKind);
|
|
88
|
+
const projectionModes = [];
|
|
89
|
+
if (mapping) {
|
|
90
|
+
projectionModes.push(mapping.nativeRead ? 'native-read' : 'entry-sync');
|
|
91
|
+
}
|
|
92
|
+
if (hasExtension)
|
|
93
|
+
projectionModes.push('materialization-extension');
|
|
94
|
+
const supported = mapping !== undefined || hasExtension;
|
|
95
|
+
if (!supported)
|
|
96
|
+
projectionModes.push('unsupported');
|
|
97
|
+
return {
|
|
98
|
+
scope,
|
|
99
|
+
contentKind,
|
|
100
|
+
support: supported ? 'supported' : 'unsupported',
|
|
101
|
+
projectionModes,
|
|
102
|
+
nativeRoleSurface: contentKind === 'agent' && supported,
|
|
103
|
+
collectionAlias: contentKind === 'skill' && mapping !== undefined
|
|
104
|
+
? 'supported'
|
|
105
|
+
: 'unsupported',
|
|
106
|
+
// A sourced provider/content policy takes precedence over the
|
|
107
|
+
// repository-wide conservative new-session decision.
|
|
108
|
+
catalogRefresh: resolveCatalogRefreshPolicy(supported, refreshPolicies[contentKind]),
|
|
109
|
+
...(supported
|
|
110
|
+
? {}
|
|
111
|
+
: {
|
|
112
|
+
unsupportedReason: `${adapter.displayName} has no ${scope} ${contentKind} projection`,
|
|
113
|
+
}),
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const REGISTRATIONS = [
|
|
119
|
+
{
|
|
120
|
+
adapter: claudeAdapter,
|
|
121
|
+
extensions: [],
|
|
122
|
+
capabilities: capabilitiesFor(claudeAdapter),
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
adapter: cursorAdapter,
|
|
126
|
+
get extensions() {
|
|
127
|
+
return [cursorMaterializationExtension];
|
|
128
|
+
},
|
|
129
|
+
capabilities: capabilitiesFor(cursorAdapter, ['agent']),
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
adapter: codexAdapter,
|
|
133
|
+
get extensions() {
|
|
134
|
+
return [codexMaterializationExtension];
|
|
135
|
+
},
|
|
136
|
+
capabilities: capabilitiesFor(codexAdapter, ['agent']),
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
adapter: copilotAdapter,
|
|
140
|
+
extensions: [],
|
|
141
|
+
capabilities: capabilitiesFor(copilotAdapter),
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
adapter: geminiAdapter,
|
|
145
|
+
extensions: [],
|
|
146
|
+
capabilities: capabilitiesFor(geminiAdapter),
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
export function validateProviderRegistrations(registrations) {
|
|
150
|
+
const names = new Set();
|
|
151
|
+
for (const registration of registrations) {
|
|
152
|
+
const name = registration.adapter.name;
|
|
153
|
+
if (names.has(name)) {
|
|
154
|
+
throw new Error(`Provider ${name} is registered more than once`);
|
|
155
|
+
}
|
|
156
|
+
names.add(name);
|
|
157
|
+
for (const extension of registration.extensions) {
|
|
158
|
+
if (extension.provider !== name) {
|
|
159
|
+
throw new Error(`Provider ${name} owns contradictory extension ${extension.provider}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const scope of SCOPES) {
|
|
163
|
+
for (const contentKind of CONTENT_KINDS) {
|
|
164
|
+
const rows = registration.capabilities.filter((capability) => capability.scope === scope &&
|
|
165
|
+
capability.contentKind === contentKind);
|
|
166
|
+
if (rows.length !== 1) {
|
|
167
|
+
throw new Error(`Provider ${name} must register exactly one ${scope} ${contentKind} capability`);
|
|
168
|
+
}
|
|
169
|
+
const [row] = rows;
|
|
170
|
+
if ((row.support === 'unsupported') !==
|
|
171
|
+
row.projectionModes.includes('unsupported')) {
|
|
172
|
+
throw new Error(`Provider ${name} has contradictory ${scope} ${contentKind} support`);
|
|
173
|
+
}
|
|
174
|
+
if (row.support === 'unsupported' &&
|
|
175
|
+
row.catalogRefresh.state !== 'unknown') {
|
|
176
|
+
throw new Error(`Provider ${name} has unsupported ${scope} ${contentKind} with non-unknown refresh policy`);
|
|
177
|
+
}
|
|
178
|
+
if (!hasValidRefreshProvenance(row.catalogRefresh)) {
|
|
179
|
+
throw new Error(`Provider ${name} has invalid ${scope} ${contentKind} refresh policy provenance`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export function getProviderRegistrations() {
|
|
186
|
+
validateProviderRegistrations(REGISTRATIONS);
|
|
187
|
+
return REGISTRATIONS;
|
|
188
|
+
}
|
|
189
|
+
export async function resolveProviderScopeContext(input) {
|
|
190
|
+
const registrations = input.registrations ?? getProviderRegistrations();
|
|
191
|
+
validateProviderRegistrations(registrations);
|
|
192
|
+
const detection = await Promise.all(registrations.map(async ({ adapter }) => ({
|
|
193
|
+
adapter,
|
|
194
|
+
detected: await adapter.detect(input.scopeRoot),
|
|
195
|
+
})));
|
|
196
|
+
const detectedProviders = detection
|
|
197
|
+
.filter(({ detected }) => detected)
|
|
198
|
+
.map(({ adapter }) => adapter.name);
|
|
199
|
+
return recomputeProviderScopeContext({
|
|
200
|
+
scope: input.scope,
|
|
201
|
+
configSource: join(input.scope === 'project' ? '<project>' : '~', '.oat', 'sync', 'config.json'),
|
|
202
|
+
detectedProviders,
|
|
203
|
+
registrations,
|
|
204
|
+
}, input.config);
|
|
205
|
+
}
|
|
206
|
+
export function recomputeProviderScopeContext(snapshot, config) {
|
|
207
|
+
const detected = new Set(snapshot.detectedProviders);
|
|
208
|
+
const active = new Set();
|
|
209
|
+
const detectedUnset = [];
|
|
210
|
+
const detectedDisabled = [];
|
|
211
|
+
const activation = snapshot.registrations.map(({ adapter }) => {
|
|
212
|
+
const isDetected = detected.has(adapter.name);
|
|
213
|
+
const configured = config.providers[adapter.name]?.enabled;
|
|
214
|
+
const isActive = configured === true || (configured === undefined && isDetected);
|
|
215
|
+
if (isActive)
|
|
216
|
+
active.add(adapter.name);
|
|
217
|
+
if (configured === undefined && isDetected)
|
|
218
|
+
detectedUnset.push(adapter.name);
|
|
219
|
+
if (configured === false && isDetected)
|
|
220
|
+
detectedDisabled.push(adapter.name);
|
|
221
|
+
const source = configured === true
|
|
222
|
+
? 'config-enabled'
|
|
223
|
+
: configured === false
|
|
224
|
+
? 'config-disabled'
|
|
225
|
+
: isActive
|
|
226
|
+
? 'detected-unset'
|
|
227
|
+
: 'undetected-unset';
|
|
228
|
+
return {
|
|
229
|
+
provider: adapter.name,
|
|
230
|
+
state: isActive ? 'active' : 'inactive',
|
|
231
|
+
source,
|
|
232
|
+
reason: source === 'config-enabled'
|
|
233
|
+
? 'Explicitly enabled in sync config'
|
|
234
|
+
: source === 'config-disabled'
|
|
235
|
+
? 'Explicitly disabled in sync config'
|
|
236
|
+
: source === 'detected-unset'
|
|
237
|
+
? 'Detected with no explicit provider setting'
|
|
238
|
+
: 'Not detected and no explicit provider setting',
|
|
239
|
+
};
|
|
240
|
+
});
|
|
241
|
+
return {
|
|
242
|
+
...snapshot,
|
|
243
|
+
activeProviders: snapshot.registrations
|
|
244
|
+
.map(({ adapter }) => adapter.name)
|
|
245
|
+
.filter((name) => active.has(name)),
|
|
246
|
+
mismatches: {
|
|
247
|
+
detectedUnset,
|
|
248
|
+
detectedDisabled,
|
|
249
|
+
},
|
|
250
|
+
activation,
|
|
251
|
+
};
|
|
252
|
+
}
|