@xenosystem/agent-interface-core 0.1.3
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/LICENSE +67 -0
- package/dist/agentDiscovery.d.ts +97 -0
- package/dist/agentDiscovery.d.ts.map +1 -0
- package/dist/agentDiscovery.js +93 -0
- package/dist/agentDiscovery.js.map +1 -0
- package/dist/capabilityRouting.d.ts +72 -0
- package/dist/capabilityRouting.d.ts.map +1 -0
- package/dist/capabilityRouting.js +124 -0
- package/dist/capabilityRouting.js.map +1 -0
- package/dist/capabilityTier.d.ts +105 -0
- package/dist/capabilityTier.d.ts.map +1 -0
- package/dist/capabilityTier.js +120 -0
- package/dist/capabilityTier.js.map +1 -0
- package/dist/combinationVerification.d.ts +101 -0
- package/dist/combinationVerification.d.ts.map +1 -0
- package/dist/combinationVerification.js +115 -0
- package/dist/combinationVerification.js.map +1 -0
- package/dist/context/agentAttachedContextPrompt.d.ts +13 -0
- package/dist/context/agentAttachedContextPrompt.d.ts.map +1 -0
- package/dist/context/agentAttachedContextPrompt.js +50 -0
- package/dist/context/agentAttachedContextPrompt.js.map +1 -0
- package/dist/context/agentModelContext.d.ts +77 -0
- package/dist/context/agentModelContext.d.ts.map +1 -0
- package/dist/context/agentModelContext.js +297 -0
- package/dist/context/agentModelContext.js.map +1 -0
- package/dist/fanOutPlanner.d.ts +65 -0
- package/dist/fanOutPlanner.d.ts.map +1 -0
- package/dist/fanOutPlanner.js +78 -0
- package/dist/fanOutPlanner.js.map +1 -0
- package/dist/fleetBoardProjection.d.ts +143 -0
- package/dist/fleetBoardProjection.d.ts.map +1 -0
- package/dist/fleetBoardProjection.js +156 -0
- package/dist/fleetBoardProjection.js.map +1 -0
- package/dist/fleetProjection.d.ts +63 -0
- package/dist/fleetProjection.d.ts.map +1 -0
- package/dist/fleetProjection.js +86 -0
- package/dist/fleetProjection.js.map +1 -0
- package/dist/hostBackedCapabilities.d.ts +50 -0
- package/dist/hostBackedCapabilities.d.ts.map +1 -0
- package/dist/hostBackedCapabilities.js +66 -0
- package/dist/hostBackedCapabilities.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +134 -0
- package/dist/index.js.map +1 -0
- package/dist/intakeBoardProjection.d.ts +75 -0
- package/dist/intakeBoardProjection.d.ts.map +1 -0
- package/dist/intakeBoardProjection.js +90 -0
- package/dist/intakeBoardProjection.js.map +1 -0
- package/dist/intakeClaim.d.ts +156 -0
- package/dist/intakeClaim.d.ts.map +1 -0
- package/dist/intakeClaim.js +190 -0
- package/dist/intakeClaim.js.map +1 -0
- package/dist/knowledgeBoardProjection.d.ts +57 -0
- package/dist/knowledgeBoardProjection.d.ts.map +1 -0
- package/dist/knowledgeBoardProjection.js +74 -0
- package/dist/knowledgeBoardProjection.js.map +1 -0
- package/dist/landingOverlap.d.ts +127 -0
- package/dist/landingOverlap.d.ts.map +1 -0
- package/dist/landingOverlap.js +107 -0
- package/dist/landingOverlap.js.map +1 -0
- package/dist/landingQueue.d.ts +152 -0
- package/dist/landingQueue.d.ts.map +1 -0
- package/dist/landingQueue.js +258 -0
- package/dist/landingQueue.js.map +1 -0
- package/dist/markdown/markdownWindowsPaths.d.ts +20 -0
- package/dist/markdown/markdownWindowsPaths.d.ts.map +1 -0
- package/dist/markdown/markdownWindowsPaths.js +208 -0
- package/dist/markdown/markdownWindowsPaths.js.map +1 -0
- package/dist/reviewProjection.d.ts +118 -0
- package/dist/reviewProjection.d.ts.map +1 -0
- package/dist/reviewProjection.js +133 -0
- package/dist/reviewProjection.js.map +1 -0
- package/dist/runDiff.d.ts +86 -0
- package/dist/runDiff.d.ts.map +1 -0
- package/dist/runDiff.js +103 -0
- package/dist/runDiff.js.map +1 -0
- package/dist/runtime/agentReasoningEffort.d.ts +22 -0
- package/dist/runtime/agentReasoningEffort.d.ts.map +1 -0
- package/dist/runtime/agentReasoningEffort.js +76 -0
- package/dist/runtime/agentReasoningEffort.js.map +1 -0
- package/dist/runtime/agentRuntimeProvider.d.ts +12 -0
- package/dist/runtime/agentRuntimeProvider.d.ts.map +1 -0
- package/dist/runtime/agentRuntimeProvider.js +294 -0
- package/dist/runtime/agentRuntimeProvider.js.map +1 -0
- package/dist/runtime/agentRuntimeProviderTypes.d.ts +100 -0
- package/dist/runtime/agentRuntimeProviderTypes.d.ts.map +1 -0
- package/dist/runtime/agentRuntimeProviderTypes.js +2 -0
- package/dist/runtime/agentRuntimeProviderTypes.js.map +1 -0
- package/dist/runtime/conversationRuntime.d.ts +53 -0
- package/dist/runtime/conversationRuntime.d.ts.map +1 -0
- package/dist/runtime/conversationRuntime.js +207 -0
- package/dist/runtime/conversationRuntime.js.map +1 -0
- package/dist/runtime/legacyAgentRuntimeEvents.d.ts +65 -0
- package/dist/runtime/legacyAgentRuntimeEvents.d.ts.map +1 -0
- package/dist/runtime/legacyAgentRuntimeEvents.js +104 -0
- package/dist/runtime/legacyAgentRuntimeEvents.js.map +1 -0
- package/dist/runtimeProjection.d.ts +19 -0
- package/dist/runtimeProjection.d.ts.map +1 -0
- package/dist/runtimeProjection.js +133 -0
- package/dist/runtimeProjection.js.map +1 -0
- package/dist/sessionBoardProjection.d.ts +84 -0
- package/dist/sessionBoardProjection.d.ts.map +1 -0
- package/dist/sessionBoardProjection.js +103 -0
- package/dist/sessionBoardProjection.js.map +1 -0
- package/dist/sessionMode.d.ts +115 -0
- package/dist/sessionMode.d.ts.map +1 -0
- package/dist/sessionMode.js +98 -0
- package/dist/sessionMode.js.map +1 -0
- package/dist/workspace/workspaceSelectionContinuation.d.ts +8 -0
- package/dist/workspace/workspaceSelectionContinuation.d.ts.map +1 -0
- package/dist/workspace/workspaceSelectionContinuation.js +18 -0
- package/dist/workspace/workspaceSelectionContinuation.js.map +1 -0
- package/dist/workspaceKnowledge.d.ts +90 -0
- package/dist/workspaceKnowledge.d.ts.map +1 -0
- package/dist/workspaceKnowledge.js +103 -0
- package/dist/workspaceKnowledge.js.map +1 -0
- package/dist/writeLease.d.ts +92 -0
- package/dist/writeLease.d.ts.map +1 -0
- package/dist/writeLease.js +108 -0
- package/dist/writeLease.js.map +1 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
XENO Agent — Proprietary Software License
|
|
2
|
+
Copyright © 2026 XENO Corporation. All rights reserved.
|
|
3
|
+
|
|
4
|
+
This software, including its source code, compiled binaries, published packages,
|
|
5
|
+
assets, and accompanying documentation (collectively, the "Software"), is the
|
|
6
|
+
proprietary and confidential property of XENO Corporation ("XENO"). The Software
|
|
7
|
+
is licensed for use, not sold, and no title to or ownership of the Software is
|
|
8
|
+
transferred to any user.
|
|
9
|
+
|
|
10
|
+
1. GRANT OF USE
|
|
11
|
+
Subject to a separate written agreement and/or the terms of service published
|
|
12
|
+
at https://xenostudio.ai, XENO grants the end user a limited, non-exclusive,
|
|
13
|
+
non-transferable, revocable license to install and use the Software for its
|
|
14
|
+
intended purpose. The standalone desktop application ("the Agent") may be used
|
|
15
|
+
locally at no charge; connected platform features — hosted agent runs, model
|
|
16
|
+
inference, credits, and account services — are governed by the applicable
|
|
17
|
+
subscription and the XENO terms of service.
|
|
18
|
+
|
|
19
|
+
2. PACKAGE DISTRIBUTION
|
|
20
|
+
The `@xeno-corporation/xeno-agent-interface-*` and
|
|
21
|
+
`@xeno-corporation/xeno-agents-client` packages are published to a PRIVATE
|
|
22
|
+
registry and are licensed for use solely by XENO products and by parties
|
|
23
|
+
holding a separate written agreement with XENO. Access credentials to that
|
|
24
|
+
registry do not grant redistribution rights. Publication of any package in
|
|
25
|
+
this repository to a public registry is prohibited without written
|
|
26
|
+
authorization from XENO.
|
|
27
|
+
|
|
28
|
+
3. RESTRICTIONS
|
|
29
|
+
Except to the extent expressly permitted by applicable law or by a separate
|
|
30
|
+
written agreement with XENO, you may NOT: (a) copy, redistribute, sell, rent,
|
|
31
|
+
lease, sublicense, or otherwise transfer the Software; (b) modify, adapt,
|
|
32
|
+
translate, or create derivative works of the Software; (c) reverse-engineer,
|
|
33
|
+
decompile, or disassemble the Software, or attempt to derive its source code;
|
|
34
|
+
(d) remove, obscure, or alter any proprietary notices; or (e) use the Software
|
|
35
|
+
to build a competing product.
|
|
36
|
+
|
|
37
|
+
4. RESERVATION OF RIGHTS
|
|
38
|
+
All rights not expressly granted are reserved by XENO Corporation. The Software
|
|
39
|
+
is protected by copyright and other intellectual-property laws and treaties.
|
|
40
|
+
|
|
41
|
+
5. DISCLAIMER OF WARRANTY
|
|
42
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT WARRANTY OF ANY
|
|
43
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
44
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THE
|
|
45
|
+
SOFTWARE EXECUTES AGENT-DIRECTED OPERATIONS AGAINST A USER-SELECTED WORKSPACE,
|
|
46
|
+
INCLUDING FILE AND PROCESS ACTIONS; THE USER IS RESPONSIBLE FOR THE WORKSPACES
|
|
47
|
+
AND PERMISSIONS THEY GRANT IT.
|
|
48
|
+
|
|
49
|
+
6. LIMITATION OF LIABILITY
|
|
50
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL XENO CORPORATION BE
|
|
51
|
+
LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE
|
|
52
|
+
DAMAGES, OR ANY LOSS OF PROFITS OR DATA, ARISING FROM OR RELATED TO THE USE OF
|
|
53
|
+
OR INABILITY TO USE THE SOFTWARE.
|
|
54
|
+
|
|
55
|
+
7. THIRD-PARTY COMPONENTS
|
|
56
|
+
The Software includes third-party open-source components, each licensed under
|
|
57
|
+
its own terms; those terms govern those components and are not superseded by
|
|
58
|
+
this license. It also composes third-party agent providers over the Agent
|
|
59
|
+
Client Protocol and hosted APIs; use of those providers is governed by their
|
|
60
|
+
own terms.
|
|
61
|
+
|
|
62
|
+
For licensing inquiries, contact: legal@xenostudio.ai
|
|
63
|
+
|
|
64
|
+
NOTE TO OPERATOR: confirm the exact legal entity name and notice/contact details
|
|
65
|
+
with counsel before public distribution and code-signing (the code-signing
|
|
66
|
+
publisher name must match the registered entity). No public distribution of this
|
|
67
|
+
product is authorized by this file — see docs/PRODUCT_STATUS.md.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding the agent CLIs already installed on this machine — ADE §5.2.
|
|
3
|
+
*
|
|
4
|
+
* @unwired-by-design ADE §9 step 6 — this is the DECISION half; the probe that
|
|
5
|
+
* walks `PATH` is node-side and belongs with the composition, and the surface
|
|
6
|
+
* that renders "found, enable?" does not exist yet. Deliberately built first
|
|
7
|
+
* and alone: the rules here are about what discovery must NOT do — never mark
|
|
8
|
+
* something enabled, never execute a binary to identify it — and those are
|
|
9
|
+
* exactly the rules that get quietly relaxed while wiring a UI. Settling them
|
|
10
|
+
* against a pure function, with gates, is cheaper than arguing them back later.
|
|
11
|
+
*
|
|
12
|
+
* §5.2 ranks this above deeper capabilities, and says why: *"A developer whose
|
|
13
|
+
* existing agent is not found will never reach any other pillar of this
|
|
14
|
+
* product."* Someone who already runs Claude Code or Codex should see it
|
|
15
|
+
* offered, not be asked to configure a path for something sitting on their
|
|
16
|
+
* `PATH`.
|
|
17
|
+
*
|
|
18
|
+
* Pure. It is handed the result of looking, and decides what that means — so
|
|
19
|
+
* every rule below is testable without a filesystem, and the node-side probe
|
|
20
|
+
* stays a few lines with no policy in it.
|
|
21
|
+
*
|
|
22
|
+
* ## 🔴 Found is OFFERED, never ENABLED
|
|
23
|
+
*
|
|
24
|
+
* §5.2's words are "scan `PATH` for known agent CLIs and **offer** to enable
|
|
25
|
+
* them". The distinction is the whole safety story: enabling an agent means
|
|
26
|
+
* this product will later SPAWN that binary. Auto-enabling whatever happens to
|
|
27
|
+
* be on `PATH` would execute third-party programs the user never pointed at us
|
|
28
|
+
* — and `PATH` is not a trust boundary, it is a convenience. So discovery
|
|
29
|
+
* produces candidates, and a human turns them on.
|
|
30
|
+
*
|
|
31
|
+
* ## 🔴 Presence is the signal — the binary is NOT executed to identify it
|
|
32
|
+
*
|
|
33
|
+
* The obvious way to confirm `claude` on `PATH` is Claude Code is to run
|
|
34
|
+
* `claude --version`. That executes an unknown program to find out whether it
|
|
35
|
+
* is safe to execute, which is backwards. Worse, `PATH` is attacker-influenced
|
|
36
|
+
* in exactly the environments this matters in (a project-local `node_modules/
|
|
37
|
+
* .bin`, a compromised shell profile).
|
|
38
|
+
*
|
|
39
|
+
* So detection is presence plus location, and version probing is a SEPARATE
|
|
40
|
+
* step taken after a human has enabled the agent. That is why `version` is
|
|
41
|
+
* absent here rather than optional-and-usually-missing.
|
|
42
|
+
*/
|
|
43
|
+
/** An agent CLI this product knows how to drive. */
|
|
44
|
+
export interface KnownAgentCli {
|
|
45
|
+
/** Stable id — becomes the ACP provider id when enabled. */
|
|
46
|
+
id: string;
|
|
47
|
+
displayName: string;
|
|
48
|
+
/**
|
|
49
|
+
* Executable names to look for, in preference order.
|
|
50
|
+
*
|
|
51
|
+
* A list because the same agent ships under different names per platform and
|
|
52
|
+
* install method, and picking one arbitrarily is how a real install goes
|
|
53
|
+
* undetected.
|
|
54
|
+
*/
|
|
55
|
+
executables: string[];
|
|
56
|
+
}
|
|
57
|
+
/** What looking on disk found. Supplied by the composition. */
|
|
58
|
+
export interface AgentCliProbeResult {
|
|
59
|
+
executable: string;
|
|
60
|
+
/** Absolute path, when found. Absent means not present. */
|
|
61
|
+
path?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface DiscoveredAgentCli {
|
|
64
|
+
id: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
/** The executable that matched, and where. */
|
|
67
|
+
executable: string;
|
|
68
|
+
path: string;
|
|
69
|
+
/**
|
|
70
|
+
* 🔴 ALWAYS false from discovery. Present so the shape a surface renders
|
|
71
|
+
* cannot express "found and already on" — enabling is a human act, and a
|
|
72
|
+
* field that could arrive true would eventually arrive true by accident.
|
|
73
|
+
*/
|
|
74
|
+
enabled: false;
|
|
75
|
+
}
|
|
76
|
+
export interface AgentDiscoveryResult {
|
|
77
|
+
found: DiscoveredAgentCli[];
|
|
78
|
+
/** Known agents that are NOT installed — reported, not silently omitted, so a
|
|
79
|
+
* surface can say "Codex: not found" rather than leaving a user wondering
|
|
80
|
+
* whether it was even looked for. */
|
|
81
|
+
missing: Array<{
|
|
82
|
+
id: string;
|
|
83
|
+
displayName: string;
|
|
84
|
+
searched: string[];
|
|
85
|
+
}>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Decides what a set of probe results means.
|
|
89
|
+
*
|
|
90
|
+
* `probes` is every executable that was looked for, whether or not it was
|
|
91
|
+
* found — a caller that only passed hits could not distinguish "not installed"
|
|
92
|
+
* from "not searched", and those are different answers.
|
|
93
|
+
*/
|
|
94
|
+
export declare function discoverAgentClis(known: readonly KnownAgentCli[], probes: readonly AgentCliProbeResult[]): AgentDiscoveryResult;
|
|
95
|
+
/** Every executable name that must be probed for a given catalog. */
|
|
96
|
+
export declare function executablesToProbe(known: readonly KnownAgentCli[]): string[];
|
|
97
|
+
//# sourceMappingURL=agentDiscovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentDiscovery.d.ts","sourceRoot":"","sources":["../src/agentDiscovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,OAAO,EAAE,KAAK,CAAA;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,kBAAkB,EAAE,CAAA;IAC3B;;0CAEsC;IACtC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CACxE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,MAAM,EAAE,SAAS,mBAAmB,EAAE,GACrC,oBAAoB,CAmCtB;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,EAAE,CAM5E"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding the agent CLIs already installed on this machine — ADE §5.2.
|
|
3
|
+
*
|
|
4
|
+
* @unwired-by-design ADE §9 step 6 — this is the DECISION half; the probe that
|
|
5
|
+
* walks `PATH` is node-side and belongs with the composition, and the surface
|
|
6
|
+
* that renders "found, enable?" does not exist yet. Deliberately built first
|
|
7
|
+
* and alone: the rules here are about what discovery must NOT do — never mark
|
|
8
|
+
* something enabled, never execute a binary to identify it — and those are
|
|
9
|
+
* exactly the rules that get quietly relaxed while wiring a UI. Settling them
|
|
10
|
+
* against a pure function, with gates, is cheaper than arguing them back later.
|
|
11
|
+
*
|
|
12
|
+
* §5.2 ranks this above deeper capabilities, and says why: *"A developer whose
|
|
13
|
+
* existing agent is not found will never reach any other pillar of this
|
|
14
|
+
* product."* Someone who already runs Claude Code or Codex should see it
|
|
15
|
+
* offered, not be asked to configure a path for something sitting on their
|
|
16
|
+
* `PATH`.
|
|
17
|
+
*
|
|
18
|
+
* Pure. It is handed the result of looking, and decides what that means — so
|
|
19
|
+
* every rule below is testable without a filesystem, and the node-side probe
|
|
20
|
+
* stays a few lines with no policy in it.
|
|
21
|
+
*
|
|
22
|
+
* ## 🔴 Found is OFFERED, never ENABLED
|
|
23
|
+
*
|
|
24
|
+
* §5.2's words are "scan `PATH` for known agent CLIs and **offer** to enable
|
|
25
|
+
* them". The distinction is the whole safety story: enabling an agent means
|
|
26
|
+
* this product will later SPAWN that binary. Auto-enabling whatever happens to
|
|
27
|
+
* be on `PATH` would execute third-party programs the user never pointed at us
|
|
28
|
+
* — and `PATH` is not a trust boundary, it is a convenience. So discovery
|
|
29
|
+
* produces candidates, and a human turns them on.
|
|
30
|
+
*
|
|
31
|
+
* ## 🔴 Presence is the signal — the binary is NOT executed to identify it
|
|
32
|
+
*
|
|
33
|
+
* The obvious way to confirm `claude` on `PATH` is Claude Code is to run
|
|
34
|
+
* `claude --version`. That executes an unknown program to find out whether it
|
|
35
|
+
* is safe to execute, which is backwards. Worse, `PATH` is attacker-influenced
|
|
36
|
+
* in exactly the environments this matters in (a project-local `node_modules/
|
|
37
|
+
* .bin`, a compromised shell profile).
|
|
38
|
+
*
|
|
39
|
+
* So detection is presence plus location, and version probing is a SEPARATE
|
|
40
|
+
* step taken after a human has enabled the agent. That is why `version` is
|
|
41
|
+
* absent here rather than optional-and-usually-missing.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* Decides what a set of probe results means.
|
|
45
|
+
*
|
|
46
|
+
* `probes` is every executable that was looked for, whether or not it was
|
|
47
|
+
* found — a caller that only passed hits could not distinguish "not installed"
|
|
48
|
+
* from "not searched", and those are different answers.
|
|
49
|
+
*/
|
|
50
|
+
export function discoverAgentClis(known, probes) {
|
|
51
|
+
const byExecutable = new Map();
|
|
52
|
+
for (const probe of probes) {
|
|
53
|
+
// First writer wins: probes arrive in the order they were searched, and a
|
|
54
|
+
// later duplicate is a second hit for the same name, not a better one.
|
|
55
|
+
if (probe.path && !byExecutable.has(probe.executable)) {
|
|
56
|
+
byExecutable.set(probe.executable, probe.path);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const found = [];
|
|
60
|
+
const missing = [];
|
|
61
|
+
for (const agent of known) {
|
|
62
|
+
// Preference order is the DECLARED order, so a machine with two names
|
|
63
|
+
// installed resolves the same way every time.
|
|
64
|
+
const hit = agent.executables.find((executable) => byExecutable.has(executable));
|
|
65
|
+
if (hit) {
|
|
66
|
+
found.push({
|
|
67
|
+
id: agent.id,
|
|
68
|
+
displayName: agent.displayName,
|
|
69
|
+
executable: hit,
|
|
70
|
+
path: byExecutable.get(hit),
|
|
71
|
+
enabled: false,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
missing.push({
|
|
76
|
+
id: agent.id,
|
|
77
|
+
displayName: agent.displayName,
|
|
78
|
+
searched: [...agent.executables],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { found, missing };
|
|
83
|
+
}
|
|
84
|
+
/** Every executable name that must be probed for a given catalog. */
|
|
85
|
+
export function executablesToProbe(known) {
|
|
86
|
+
const seen = new Set();
|
|
87
|
+
for (const agent of known) {
|
|
88
|
+
for (const executable of agent.executables)
|
|
89
|
+
seen.add(executable);
|
|
90
|
+
}
|
|
91
|
+
return [...seen];
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=agentDiscovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentDiscovery.js","sourceRoot":"","sources":["../src/agentDiscovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AA8CH;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAA+B,EAC/B,MAAsC;IAEtC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,0EAA0E;QAC1E,uEAAuE;QACvE,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YACtD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QAChD,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAyB,EAAE,CAAA;IACtC,MAAM,OAAO,GAAoC,EAAE,CAAA;IAEnD,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,sEAAsE;QACtE,8CAA8C;QAC9C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAA;QAChF,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,UAAU,EAAE,GAAG;gBACf,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAE;gBAC5B,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;aACjC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;AAC3B,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,kBAAkB,CAAC,KAA+B;IAChE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,WAAW;YAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IAClE,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which agents may run a task — ADE §5.2's capability matcher.
|
|
3
|
+
*
|
|
4
|
+
* Reached over the host boundary as `fleet.route` (§5.2's "capability matcher
|
|
5
|
+
* behind host methods"), which is what makes the refusal OBSERVABLE — a refusal
|
|
6
|
+
* nothing can ask for is not one anyone can act on.
|
|
7
|
+
*
|
|
8
|
+
* Pure and provider-neutral: it takes descriptors and returns a decision. It
|
|
9
|
+
* starts nothing, so it can be asked speculatively ("could this task run?")
|
|
10
|
+
* without side effects — which is what a scheduler needs before it commits.
|
|
11
|
+
*
|
|
12
|
+
* ## The four rules, each of which a naive matcher gets wrong
|
|
13
|
+
*
|
|
14
|
+
* 1. **An ABSENT capability is NOT declared.** `AgentCapabilityMatrix` is a
|
|
15
|
+
* `Partial<Record<…>>`, so a missing key is the common case, not an
|
|
16
|
+
* exception. Reading absence as "probably fine" is how a task reaches an
|
|
17
|
+
* agent that never claimed it could do the work.
|
|
18
|
+
* 2. **`unsupported` and `blocked` are refusals**, and they are DIFFERENT
|
|
19
|
+
* refusals — one says never, the other says not now. Both keep the agent out
|
|
20
|
+
* of the eligible set; only the reason differs, and the reason is what the
|
|
21
|
+
* user acts on.
|
|
22
|
+
* 3. **`degraded` is eligible, and must be reported.** Refusing it would make
|
|
23
|
+
* the product unusable on any partially-configured agent; hiding it would
|
|
24
|
+
* silently give someone a worse run than they asked for. So it routes, and
|
|
25
|
+
* it says so.
|
|
26
|
+
* 4. **An unavailable PROVIDER is ineligible however good its matrix is.** A
|
|
27
|
+
* capability declared by an agent that cannot run is a claim about a thing
|
|
28
|
+
* that will not happen.
|
|
29
|
+
*/
|
|
30
|
+
import type { AgentHarnessCapability, AgentRuntimeProviderDescriptor } from '@xenosystem/agent-interface-contract';
|
|
31
|
+
/** Why one provider was ruled out, in terms a user can act on. */
|
|
32
|
+
export interface CapabilityRejection {
|
|
33
|
+
providerId: string;
|
|
34
|
+
/** The capability that ruled it out. Absent when the PROVIDER is unavailable
|
|
35
|
+
* rather than any particular capability being missing. */
|
|
36
|
+
capability?: AgentHarnessCapability;
|
|
37
|
+
reason: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CapabilityMatch {
|
|
40
|
+
providerId: string;
|
|
41
|
+
/**
|
|
42
|
+
* Capabilities this provider serves in a `degraded` state.
|
|
43
|
+
*
|
|
44
|
+
* Non-empty means the task CAN run here and will run worse. Surfacing it is
|
|
45
|
+
* the difference between an informed choice and a silent downgrade.
|
|
46
|
+
*/
|
|
47
|
+
degraded: AgentHarnessCapability[];
|
|
48
|
+
}
|
|
49
|
+
export type CapabilityRoutingDecision = {
|
|
50
|
+
routable: true;
|
|
51
|
+
matches: CapabilityMatch[];
|
|
52
|
+
rejected: CapabilityRejection[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 🔴 No agent can do this. `reason` names the specific capability nobody
|
|
56
|
+
* declared, because "no agent is available" sends someone to check their
|
|
57
|
+
* network while the real answer is that no installed agent does this at all.
|
|
58
|
+
*/
|
|
59
|
+
| {
|
|
60
|
+
routable: false;
|
|
61
|
+
reason: string;
|
|
62
|
+
rejected: CapabilityRejection[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Decides which providers may run a task requiring `required`.
|
|
66
|
+
*
|
|
67
|
+
* A task requiring NOTHING is routable to every runnable provider — an empty
|
|
68
|
+
* requirement list is not a trick question, and refusing it would make the
|
|
69
|
+
* matcher unusable as a general router.
|
|
70
|
+
*/
|
|
71
|
+
export declare function routeByCapability(providers: readonly AgentRuntimeProviderDescriptor[], required: readonly AgentHarnessCapability[]): CapabilityRoutingDecision;
|
|
72
|
+
//# sourceMappingURL=capabilityRouting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityRouting.d.ts","sourceRoot":"","sources":["../src/capabilityRouting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAGV,sBAAsB,EACtB,8BAA8B,EAC/B,MAAM,sCAAsC,CAAA;AAE7C,kEAAkE;AAClE,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB;+DAC2D;IAC3D,UAAU,CAAC,EAAE,sBAAsB,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,QAAQ,EAAE,sBAAsB,EAAE,CAAA;CACnC;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,EAAE,mBAAmB,EAAE,CAAA;CAAE;AACjF;;;;GAIG;GACD;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAA;AAyBxE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,8BAA8B,EAAE,EACpD,QAAQ,EAAE,SAAS,sBAAsB,EAAE,GAC1C,yBAAyB,CA+C3B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which agents may run a task — ADE §5.2's capability matcher.
|
|
3
|
+
*
|
|
4
|
+
* Reached over the host boundary as `fleet.route` (§5.2's "capability matcher
|
|
5
|
+
* behind host methods"), which is what makes the refusal OBSERVABLE — a refusal
|
|
6
|
+
* nothing can ask for is not one anyone can act on.
|
|
7
|
+
*
|
|
8
|
+
* Pure and provider-neutral: it takes descriptors and returns a decision. It
|
|
9
|
+
* starts nothing, so it can be asked speculatively ("could this task run?")
|
|
10
|
+
* without side effects — which is what a scheduler needs before it commits.
|
|
11
|
+
*
|
|
12
|
+
* ## The four rules, each of which a naive matcher gets wrong
|
|
13
|
+
*
|
|
14
|
+
* 1. **An ABSENT capability is NOT declared.** `AgentCapabilityMatrix` is a
|
|
15
|
+
* `Partial<Record<…>>`, so a missing key is the common case, not an
|
|
16
|
+
* exception. Reading absence as "probably fine" is how a task reaches an
|
|
17
|
+
* agent that never claimed it could do the work.
|
|
18
|
+
* 2. **`unsupported` and `blocked` are refusals**, and they are DIFFERENT
|
|
19
|
+
* refusals — one says never, the other says not now. Both keep the agent out
|
|
20
|
+
* of the eligible set; only the reason differs, and the reason is what the
|
|
21
|
+
* user acts on.
|
|
22
|
+
* 3. **`degraded` is eligible, and must be reported.** Refusing it would make
|
|
23
|
+
* the product unusable on any partially-configured agent; hiding it would
|
|
24
|
+
* silently give someone a worse run than they asked for. So it routes, and
|
|
25
|
+
* it says so.
|
|
26
|
+
* 4. **An unavailable PROVIDER is ineligible however good its matrix is.** A
|
|
27
|
+
* capability declared by an agent that cannot run is a claim about a thing
|
|
28
|
+
* that will not happen.
|
|
29
|
+
*/
|
|
30
|
+
/** Provider availabilities that can run a turn. `degraded` can; the rest cannot. */
|
|
31
|
+
const RUNNABLE = new Set(['available', 'degraded']);
|
|
32
|
+
/** Capability statuses that permit routing. */
|
|
33
|
+
const PERMITTED = new Set([
|
|
34
|
+
'available',
|
|
35
|
+
'degraded',
|
|
36
|
+
]);
|
|
37
|
+
function refusalFor(status, capability, reason) {
|
|
38
|
+
// `unsupported` and `blocked` are different facts and the wording keeps them
|
|
39
|
+
// apart: one is a property of the agent, the other of its current state.
|
|
40
|
+
const base = status === 'unsupported'
|
|
41
|
+
? `does not support ${capability}`
|
|
42
|
+
: `has ${capability} blocked`;
|
|
43
|
+
return reason ? `${base} — ${reason}` : base;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Decides which providers may run a task requiring `required`.
|
|
47
|
+
*
|
|
48
|
+
* A task requiring NOTHING is routable to every runnable provider — an empty
|
|
49
|
+
* requirement list is not a trick question, and refusing it would make the
|
|
50
|
+
* matcher unusable as a general router.
|
|
51
|
+
*/
|
|
52
|
+
export function routeByCapability(providers, required) {
|
|
53
|
+
const matches = [];
|
|
54
|
+
const rejected = [];
|
|
55
|
+
for (const provider of providers) {
|
|
56
|
+
if (!RUNNABLE.has(provider.availability)) {
|
|
57
|
+
rejected.push({
|
|
58
|
+
providerId: provider.id,
|
|
59
|
+
reason: provider.safeUnavailableReason
|
|
60
|
+
? `is ${provider.availability} — ${provider.safeUnavailableReason}`
|
|
61
|
+
: `is ${provider.availability}`,
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const degraded = [];
|
|
66
|
+
let rejection;
|
|
67
|
+
for (const capability of required) {
|
|
68
|
+
const descriptor = provider.capabilities[capability];
|
|
69
|
+
if (!descriptor) {
|
|
70
|
+
// Rule 1. Absence is the common case, and it means NOT DECLARED.
|
|
71
|
+
rejection = {
|
|
72
|
+
providerId: provider.id,
|
|
73
|
+
capability,
|
|
74
|
+
reason: `does not declare ${capability}`,
|
|
75
|
+
};
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
if (!PERMITTED.has(descriptor.status)) {
|
|
79
|
+
rejection = {
|
|
80
|
+
providerId: provider.id,
|
|
81
|
+
capability,
|
|
82
|
+
reason: refusalFor(descriptor.status, capability, descriptor.reason),
|
|
83
|
+
};
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
if (descriptor.status === 'degraded')
|
|
87
|
+
degraded.push(capability);
|
|
88
|
+
}
|
|
89
|
+
if (rejection)
|
|
90
|
+
rejected.push(rejection);
|
|
91
|
+
else
|
|
92
|
+
matches.push({ providerId: provider.id, degraded });
|
|
93
|
+
}
|
|
94
|
+
if (matches.length > 0)
|
|
95
|
+
return { routable: true, matches, rejected };
|
|
96
|
+
return { routable: false, reason: unroutableReason(providers, required, rejected), rejected };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Why nothing can run this — named, never generic.
|
|
100
|
+
*
|
|
101
|
+
* The distinction that matters to a user: is this task impossible with what
|
|
102
|
+
* they have installed, or did every capable agent happen to be down? Those lead
|
|
103
|
+
* to completely different next actions, and "no agent available" answers
|
|
104
|
+
* neither.
|
|
105
|
+
*/
|
|
106
|
+
function unroutableReason(providers, required, rejected) {
|
|
107
|
+
if (providers.length === 0)
|
|
108
|
+
return 'No agent runtimes are configured.';
|
|
109
|
+
// A capability NO provider declares — the strongest, most actionable answer,
|
|
110
|
+
// and true regardless of whether the providers are up.
|
|
111
|
+
const undeclared = required.filter((capability) => providers.every((provider) => provider.capabilities[capability] === undefined));
|
|
112
|
+
if (undeclared.length > 0) {
|
|
113
|
+
return `No configured agent declares ${undeclared.join(', ')}.`;
|
|
114
|
+
}
|
|
115
|
+
// Every provider was ruled out by availability rather than by capability.
|
|
116
|
+
if (rejected.length > 0 && rejected.every((entry) => entry.capability === undefined)) {
|
|
117
|
+
return 'Every agent that could run this task is currently unavailable.';
|
|
118
|
+
}
|
|
119
|
+
const named = rejected.find((entry) => entry.capability !== undefined);
|
|
120
|
+
return named
|
|
121
|
+
? `No agent can run this task: every candidate ${named.reason}.`
|
|
122
|
+
: 'No agent can run this task.';
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=capabilityRouting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityRouting.js","sourceRoot":"","sources":["../src/capabilityRouting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier resolution — ADE spec §2.9, "structure comes from the substrate, not from
|
|
3
|
+
* the agent".
|
|
4
|
+
*
|
|
5
|
+
* The apparent cost of running a third-party agent in its own TUI is that it
|
|
6
|
+
* tells us nothing structured. §2.9's answer is that we should not have been
|
|
7
|
+
* asking it:
|
|
8
|
+
*
|
|
9
|
+
* > "Every run gets a sandbox. Every file write and every process spawn
|
|
10
|
+
* > therefore passes through a boundary we own — and **a boundary you own is a
|
|
11
|
+
* > sensor.** The sandbox is not only a wall; it is an observation plane. So the
|
|
12
|
+
* > question is not *how do we get the agent to narrate its work*. It is *why
|
|
13
|
+
* > are we asking the agent at all*."
|
|
14
|
+
*
|
|
15
|
+
* ## Two ways to get this wrong, and the spec names both
|
|
16
|
+
*
|
|
17
|
+
* **Understating.** §8: "Review, landing, diffs, checkpoints and the command
|
|
18
|
+
* timeline are tier-1 and therefore work for every agent in every mode,
|
|
19
|
+
* including a third-party TUI we render nothing of. **Reporting them unavailable
|
|
20
|
+
* for a third-party agent is a defect, not honest degradation — the data is in
|
|
21
|
+
* the sandbox.**"
|
|
22
|
+
*
|
|
23
|
+
* **Overstating.** §2.9: "The honest boundary: **effects are recoverable, intent
|
|
24
|
+
* is not.** Review and landing are about effects and therefore work at tier 1
|
|
25
|
+
* for every agent. Steering and reasoning capture genuinely require tier 3."
|
|
26
|
+
*
|
|
27
|
+
* So a resolver that answered "available" for everything would be as wrong as
|
|
28
|
+
* one that answered "unavailable" without a sandbox — in opposite directions,
|
|
29
|
+
* and this module is tested against both.
|
|
30
|
+
*
|
|
31
|
+
* ## There is no scraping tier
|
|
32
|
+
*
|
|
33
|
+
* §2.9: "**Explicitly excluded: parsing the TUI.** Scraping ANSI is the brittle
|
|
34
|
+
* path that breaks on every vendor UI change. We do not need it, because tier 1
|
|
35
|
+
* supplies the same facts from a source that cannot change out from under us."
|
|
36
|
+
*
|
|
37
|
+
* `CapabilityTier` therefore has no value meaning "scraped". A future
|
|
38
|
+
* contributor cannot route a capability through ANSI parsing without changing
|
|
39
|
+
* this type, which is a conversation rather than a commit.
|
|
40
|
+
*/
|
|
41
|
+
/** Where a capability's data comes from. Higher tiers carry more meaning. */
|
|
42
|
+
export type CapabilityTier = 1 | 2 | 3;
|
|
43
|
+
/**
|
|
44
|
+
* What a capability fundamentally needs.
|
|
45
|
+
*
|
|
46
|
+
* The distinction is §2.9's "honest boundary", not an implementation detail:
|
|
47
|
+
* effects leave traces in the substrate, intent exists only in the agent.
|
|
48
|
+
*/
|
|
49
|
+
export type CapabilityNeed = 'effects' | 'intent';
|
|
50
|
+
/** What this run can actually observe. */
|
|
51
|
+
export interface CapabilitySources {
|
|
52
|
+
/** Tier 1 — the sandbox filesystem and process tree. */
|
|
53
|
+
sandboxObservation: boolean;
|
|
54
|
+
/** Tier 2 — a vendor-supported side channel: hooks, JSONL traces, telemetry.
|
|
55
|
+
* NOT scraping; §2.9 excludes that outright. */
|
|
56
|
+
vendorSideChannel: boolean;
|
|
57
|
+
/** Tier 3 — the agent speaks ACP. */
|
|
58
|
+
acp: boolean;
|
|
59
|
+
}
|
|
60
|
+
export type CapabilityResolution = {
|
|
61
|
+
available: true;
|
|
62
|
+
tier: CapabilityTier;
|
|
63
|
+
reason: string;
|
|
64
|
+
} | {
|
|
65
|
+
available: false;
|
|
66
|
+
reason: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The §2.9 capability map, stated once.
|
|
70
|
+
*
|
|
71
|
+
* Kept as data rather than scattered through call sites so "is this effects or
|
|
72
|
+
* intent?" has one answer. Getting it wrong for a single capability is how a
|
|
73
|
+
* surface ends up telling a user that review is unavailable for the agent they
|
|
74
|
+
* chose — the defect §8 names.
|
|
75
|
+
*/
|
|
76
|
+
export declare const CAPABILITY_NEEDS: {
|
|
77
|
+
readonly 'file.changes': "effects";
|
|
78
|
+
readonly 'review.diff': "effects";
|
|
79
|
+
readonly 'review.hunks': "effects";
|
|
80
|
+
readonly checkpoints: "effects";
|
|
81
|
+
readonly 'command.timeline': "effects";
|
|
82
|
+
readonly landing: "effects";
|
|
83
|
+
readonly 'steering.mid-turn': "intent";
|
|
84
|
+
readonly 'reasoning.capture': "intent";
|
|
85
|
+
readonly 'permission.events': "intent";
|
|
86
|
+
readonly 'tool.semantics': "intent";
|
|
87
|
+
};
|
|
88
|
+
export type KnownCapability = keyof typeof CAPABILITY_NEEDS;
|
|
89
|
+
/**
|
|
90
|
+
* Resolves a capability to the highest tier that can actually deliver it.
|
|
91
|
+
*
|
|
92
|
+
* `available: false` is reserved for cases where NOTHING can deliver it — never
|
|
93
|
+
* used as a shorthand for "the agent did not tell us", which is the failure §8
|
|
94
|
+
* calls a defect.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveCapabilityTier(capability: KnownCapability, sources: CapabilitySources): CapabilityResolution;
|
|
97
|
+
/**
|
|
98
|
+
* True when a capability would be wrongly reported unavailable.
|
|
99
|
+
*
|
|
100
|
+
* §8 calls that a DEFECT rather than honest degradation, so it is worth being
|
|
101
|
+
* able to assert directly — a surface can check itself instead of a human
|
|
102
|
+
* noticing that review vanished for one agent.
|
|
103
|
+
*/
|
|
104
|
+
export declare function isUnderstatedCapability(capability: KnownCapability, sources: CapabilitySources, reportedAvailable: boolean): boolean;
|
|
105
|
+
//# sourceMappingURL=capabilityTier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityTier.d.ts","sourceRoot":"","sources":["../src/capabilityTier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEjD,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B;qDACiD;IACjD,iBAAiB,EAAE,OAAO,CAAA;IAC1B,qCAAqC;IACrC,GAAG,EAAE,OAAO,CAAA;CACb;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAesB,CAAA;AAEnD,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,gBAAgB,CAAA;AAE3D;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,iBAAiB,GACzB,oBAAoB,CAyCtB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,EAAE,OAAO,GACzB,OAAO,CAET"}
|