@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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session surface may SHOW โ ADE ยง5.5 attach and takeover.
|
|
3
|
+
*
|
|
4
|
+
* `session.list` answers what exists; this decides what a person is told about
|
|
5
|
+
* their own relationship to each session, and what they may do about it. Pure,
|
|
6
|
+
* in `core`, for the reason `reviewProjection` and `fleetBoardProjection` are:
|
|
7
|
+
* an honesty rule written in JSX is enforced by whoever writes the next
|
|
8
|
+
* component.
|
|
9
|
+
*
|
|
10
|
+
* ## ๐ด The lease has THREE states, not two
|
|
11
|
+
*
|
|
12
|
+
* "Locked" is not enough. *You* hold it, *another human* holds it, or the
|
|
13
|
+
* *agent* holds it โ and each implies a different action: keep typing, go find a
|
|
14
|
+
* colleague, or take over. A surface that renders the first two the same way
|
|
15
|
+
* tells one person their keystrokes are landing when they are being refused.
|
|
16
|
+
*
|
|
17
|
+
* ## Taking over is ADVICE here, never the decision
|
|
18
|
+
*
|
|
19
|
+
* `canTakeOver` exists so a button can be disabled, and that is all. The host
|
|
20
|
+
* arbitrates, and a surface that treated this as the gate would be a second
|
|
21
|
+
* implementation of the arbitration โ which is how the two come to disagree,
|
|
22
|
+
* always in the direction of the optimistic one.
|
|
23
|
+
*/
|
|
24
|
+
/** Mirrors `AgentSessionSummary` on the wire, redeclared so `core` stays free of
|
|
25
|
+
* the contract package in the direction that matters. */
|
|
26
|
+
export interface SessionBoardInput {
|
|
27
|
+
sessionId: string;
|
|
28
|
+
runId: string;
|
|
29
|
+
mode: string;
|
|
30
|
+
switchable: boolean;
|
|
31
|
+
hasProtocolChannel: boolean;
|
|
32
|
+
openedAt: number;
|
|
33
|
+
viewers: string[];
|
|
34
|
+
lease: {
|
|
35
|
+
holder: string | null;
|
|
36
|
+
heldSince: number | null;
|
|
37
|
+
interventions: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export type SessionLeaseRelation = 'agent' | 'you' | 'other-human';
|
|
41
|
+
export interface SessionBoardRow {
|
|
42
|
+
sessionId: string;
|
|
43
|
+
runId: string;
|
|
44
|
+
mode: string;
|
|
45
|
+
/** Who may write, relative to the person looking at this. */
|
|
46
|
+
lease: SessionLeaseRelation;
|
|
47
|
+
/** The other human's id, when one holds the lease. Named, never "someone". */
|
|
48
|
+
heldBy?: string;
|
|
49
|
+
/** How many times a human has taken this session over, ever. */
|
|
50
|
+
interventions: number;
|
|
51
|
+
viewers: number;
|
|
52
|
+
/** True when the person looking is one of them. */
|
|
53
|
+
youAreWatching: boolean;
|
|
54
|
+
/** Someone ELSE is watching. Worth knowing before you type into a terminal. */
|
|
55
|
+
othersWatching: number;
|
|
56
|
+
/** Advice for enabling a control โ the host still arbitrates. */
|
|
57
|
+
canTakeOver: boolean;
|
|
58
|
+
canRelease: boolean;
|
|
59
|
+
/** One line a person can act on. */
|
|
60
|
+
headline: string;
|
|
61
|
+
}
|
|
62
|
+
export interface SessionBoard {
|
|
63
|
+
rows: SessionBoardRow[];
|
|
64
|
+
notice?: string;
|
|
65
|
+
}
|
|
66
|
+
export declare function projectSessionBoard(sessions: SessionBoardInput[], viewerId: string): SessionBoard;
|
|
67
|
+
/**
|
|
68
|
+
* What to say about a snapshot of terminal output.
|
|
69
|
+
*
|
|
70
|
+
* ๐ด Truncation and emptiness are different, and neither is an error. Output
|
|
71
|
+
* that begins mid-sentence with no explanation reads as corruption; an empty
|
|
72
|
+
* terminal for a session that has genuinely printed nothing is just the truth.
|
|
73
|
+
* Only `available: false` means something went wrong.
|
|
74
|
+
*/
|
|
75
|
+
export declare function describeSessionOutput(snapshot: {
|
|
76
|
+
available: boolean;
|
|
77
|
+
output: string;
|
|
78
|
+
truncated: boolean;
|
|
79
|
+
reason?: string;
|
|
80
|
+
}): {
|
|
81
|
+
text: string;
|
|
82
|
+
notice?: string;
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=sessionBoardProjection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionBoardProjection.d.ts","sourceRoot":"","sources":["../src/sessionBoardProjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;0DAC0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;CAClF;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,CAAA;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,KAAK,EAAE,oBAAoB,CAAA;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,cAAc,EAAE,OAAO,CAAA;IACvB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAA;IACtB,iEAAiE;IACjE,WAAW,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,EAAE,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,QAAQ,EAAE,MAAM,GACf,YAAY,CAgDd;AAcD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE;IAC9C,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAapC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session surface may SHOW โ ADE ยง5.5 attach and takeover.
|
|
3
|
+
*
|
|
4
|
+
* `session.list` answers what exists; this decides what a person is told about
|
|
5
|
+
* their own relationship to each session, and what they may do about it. Pure,
|
|
6
|
+
* in `core`, for the reason `reviewProjection` and `fleetBoardProjection` are:
|
|
7
|
+
* an honesty rule written in JSX is enforced by whoever writes the next
|
|
8
|
+
* component.
|
|
9
|
+
*
|
|
10
|
+
* ## ๐ด The lease has THREE states, not two
|
|
11
|
+
*
|
|
12
|
+
* "Locked" is not enough. *You* hold it, *another human* holds it, or the
|
|
13
|
+
* *agent* holds it โ and each implies a different action: keep typing, go find a
|
|
14
|
+
* colleague, or take over. A surface that renders the first two the same way
|
|
15
|
+
* tells one person their keystrokes are landing when they are being refused.
|
|
16
|
+
*
|
|
17
|
+
* ## Taking over is ADVICE here, never the decision
|
|
18
|
+
*
|
|
19
|
+
* `canTakeOver` exists so a button can be disabled, and that is all. The host
|
|
20
|
+
* arbitrates, and a surface that treated this as the gate would be a second
|
|
21
|
+
* implementation of the arbitration โ which is how the two come to disagree,
|
|
22
|
+
* always in the direction of the optimistic one.
|
|
23
|
+
*/
|
|
24
|
+
export function projectSessionBoard(sessions, viewerId) {
|
|
25
|
+
const rows = sessions.map((session) => {
|
|
26
|
+
const lease = session.lease.holder === null
|
|
27
|
+
? 'agent'
|
|
28
|
+
: session.lease.holder === viewerId
|
|
29
|
+
? 'you'
|
|
30
|
+
: 'other-human';
|
|
31
|
+
const youAreWatching = session.viewers.includes(viewerId);
|
|
32
|
+
const othersWatching = session.viewers.filter((viewer) => viewer !== viewerId).length;
|
|
33
|
+
return {
|
|
34
|
+
sessionId: session.sessionId,
|
|
35
|
+
runId: session.runId,
|
|
36
|
+
mode: session.mode,
|
|
37
|
+
lease,
|
|
38
|
+
...(lease === 'other-human' && session.lease.holder
|
|
39
|
+
? { heldBy: session.lease.holder }
|
|
40
|
+
: {}),
|
|
41
|
+
interventions: session.lease.interventions,
|
|
42
|
+
viewers: session.viewers.length,
|
|
43
|
+
youAreWatching,
|
|
44
|
+
othersWatching,
|
|
45
|
+
// ๐ด Refused only when ANOTHER human holds it. The agent holding the lease
|
|
46
|
+
// is the ordinary case that takeover exists for, and a surface that
|
|
47
|
+
// disabled the control there would remove the feature.
|
|
48
|
+
canTakeOver: lease !== 'other-human',
|
|
49
|
+
canRelease: lease === 'you',
|
|
50
|
+
headline: headlineFor(lease, session),
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
// Newest first. A session list is read to find what is happening NOW, and the
|
|
54
|
+
// most recently opened session is the one most likely to be it.
|
|
55
|
+
rows.sort((left, right) => {
|
|
56
|
+
const leftAt = sessions.find((session) => session.sessionId === left.sessionId)?.openedAt ?? 0;
|
|
57
|
+
const rightAt = sessions.find((session) => session.sessionId === right.sessionId)?.openedAt ?? 0;
|
|
58
|
+
return rightAt === leftAt ? left.sessionId.localeCompare(right.sessionId) : rightAt - leftAt;
|
|
59
|
+
});
|
|
60
|
+
const contended = rows.filter((row) => row.lease === 'other-human').length;
|
|
61
|
+
return {
|
|
62
|
+
rows,
|
|
63
|
+
...(contended > 0
|
|
64
|
+
? {
|
|
65
|
+
notice: `${contended} session${contended === 1 ? ' is' : 's are'} being typed into by someone else. Your keystrokes there will be refused.`,
|
|
66
|
+
}
|
|
67
|
+
: {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function headlineFor(lease, session) {
|
|
71
|
+
if (lease === 'you') {
|
|
72
|
+
return 'You are typing. The agent cannot write until you hand it back.';
|
|
73
|
+
}
|
|
74
|
+
if (lease === 'other-human') {
|
|
75
|
+
return `${session.lease.holder} is typing in this session.`;
|
|
76
|
+
}
|
|
77
|
+
return session.lease.interventions > 0
|
|
78
|
+
? `The agent is driving. Taken over ${session.lease.interventions} time${session.lease.interventions === 1 ? '' : 's'} so far.`
|
|
79
|
+
: 'The agent is driving.';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* What to say about a snapshot of terminal output.
|
|
83
|
+
*
|
|
84
|
+
* ๐ด Truncation and emptiness are different, and neither is an error. Output
|
|
85
|
+
* that begins mid-sentence with no explanation reads as corruption; an empty
|
|
86
|
+
* terminal for a session that has genuinely printed nothing is just the truth.
|
|
87
|
+
* Only `available: false` means something went wrong.
|
|
88
|
+
*/
|
|
89
|
+
export function describeSessionOutput(snapshot) {
|
|
90
|
+
if (!snapshot.available) {
|
|
91
|
+
return { text: '', notice: snapshot.reason ?? 'This session could not be read.' };
|
|
92
|
+
}
|
|
93
|
+
if (snapshot.output.length === 0) {
|
|
94
|
+
return { text: '', notice: 'This session has printed nothing yet.' };
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
text: snapshot.output,
|
|
98
|
+
...(snapshot.truncated
|
|
99
|
+
? { notice: 'Earlier output has been dropped โ this is the most recent part only.' }
|
|
100
|
+
: {}),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=sessionBoardProjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionBoardProjection.js","sourceRoot":"","sources":["../src/sessionBoardProjection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session render mode and input routing โ ADE spec ยง2.8.
|
|
3
|
+
*
|
|
4
|
+
* โ
CONSUMED since 2026-08-13 by `host/session/AgentSessionService`, the ยง2.8
|
|
5
|
+
* substrate these rules were written for. It carried an `@unwired-by-design`
|
|
6
|
+
* marker until that consumer existed; wiring it was the point, so the marker is
|
|
7
|
+
* gone rather than updated.
|
|
8
|
+
*
|
|
9
|
+
* ## 1. The modes are not simultaneous
|
|
10
|
+
*
|
|
11
|
+
* ยง2.8: "The two modes are not simultaneous for one process: a CLI in
|
|
12
|
+
* interactive TUI mode is not also serving ACP. Where an agent supports both,
|
|
13
|
+
* the user switches."
|
|
14
|
+
*
|
|
15
|
+
* So selection returns exactly ONE mode. An agent that supports both is
|
|
16
|
+
* *switchable*, which is a different statement from *running both* โ and a
|
|
17
|
+
* caller handed `{nativeTui: true, acp: true}` would otherwise be free to
|
|
18
|
+
* believe the second one.
|
|
19
|
+
*
|
|
20
|
+
* ## 2. Typing never falls into a void
|
|
21
|
+
*
|
|
22
|
+
* ยง2.8: "Input is routed by the host: mid-turn steering where the agent accepts
|
|
23
|
+
* it, queued as the next turn where it does not. Typing never falls into a void,
|
|
24
|
+
* and human input is always recorded as a human intervention."
|
|
25
|
+
*
|
|
26
|
+
* `InputRouting` has no `drop` case. Not "we decided not to drop input" โ there
|
|
27
|
+
* is no value that means it, so a caller cannot silently discard a keystroke and
|
|
28
|
+
* a future contributor cannot add that path without changing this type. Every
|
|
29
|
+
* outcome is also `recordedAs: 'human-intervention'`, because ยง2.8 says human
|
|
30
|
+
* input is ALWAYS recorded as one, and an unrecorded intervention is a change in
|
|
31
|
+
* the run that the timeline cannot explain.
|
|
32
|
+
*/
|
|
33
|
+
/** What renders into the session's PTY. */
|
|
34
|
+
export type SessionRenderMode = 'native-tui' | 'acp';
|
|
35
|
+
/** What an agent is capable of, not what it is doing. */
|
|
36
|
+
export interface AgentRenderSupport {
|
|
37
|
+
/** The agent ships its own interactive TUI (Claude Code, Codex). */
|
|
38
|
+
nativeTui: boolean;
|
|
39
|
+
/** The agent can be driven headless over the protocol. */
|
|
40
|
+
acp: boolean;
|
|
41
|
+
}
|
|
42
|
+
export type SessionModeSelection = {
|
|
43
|
+
ok: true;
|
|
44
|
+
mode: SessionRenderMode;
|
|
45
|
+
/** True when the user may switch; ยง2.8 switching, never simultaneity. */
|
|
46
|
+
switchable: boolean;
|
|
47
|
+
reason: string;
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
reason: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Chooses the mode a session runs in.
|
|
54
|
+
*
|
|
55
|
+
* ยง2.8: "For a third-party agent with a good TUI, `native-tui` is the default
|
|
56
|
+
* and the right answer. Their interface is the product they built; reproducing
|
|
57
|
+
* it from protocol events yields a worse imitation of something a vendor
|
|
58
|
+
* invested years in, and it rots every time they ship an improvement."
|
|
59
|
+
*
|
|
60
|
+
* An agent supporting neither is a REFUSAL, not a fallback. Quietly picking
|
|
61
|
+
* `acp` for an agent that cannot serve it produces a session that renders
|
|
62
|
+
* nothing and reports no error โ the failure mode where a caller believes it has
|
|
63
|
+
* a working terminal.
|
|
64
|
+
*/
|
|
65
|
+
export declare function selectSessionRenderMode(support: AgentRenderSupport, preference?: SessionRenderMode): SessionModeSelection;
|
|
66
|
+
/**
|
|
67
|
+
* Where a keystroke goes.
|
|
68
|
+
*
|
|
69
|
+
* There is deliberately no `drop`. ยง2.8 is unambiguous that typing never falls
|
|
70
|
+
* into a void, and the strongest way to hold that is to leave no value that
|
|
71
|
+
* could express it.
|
|
72
|
+
*/
|
|
73
|
+
export type InputRouting = {
|
|
74
|
+
disposition: 'steer';
|
|
75
|
+
recordedAs: 'human-intervention';
|
|
76
|
+
} | {
|
|
77
|
+
disposition: 'queue';
|
|
78
|
+
recordedAs: 'human-intervention';
|
|
79
|
+
reason: string;
|
|
80
|
+
};
|
|
81
|
+
export interface InputRoutingContext {
|
|
82
|
+
/** True while the agent is mid-turn. */
|
|
83
|
+
turnInFlight: boolean;
|
|
84
|
+
/** Whether this agent accepts input during a turn. Assumption 3 PROVED this
|
|
85
|
+
* is achievable through a PTY we own โ see docs/evidence/PTY_STEERING_2026-08-11.md
|
|
86
|
+
* โ but not every agent accepts it, and claiming otherwise for one that does
|
|
87
|
+
* not would lose the input we promised never to lose. */
|
|
88
|
+
acceptsMidTurnSteering: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Where the keystrokes physically GO once routing has decided to steer.
|
|
92
|
+
*
|
|
93
|
+
* ๐ด Routing and delivery are different questions, and conflating them put
|
|
94
|
+
* typing into exactly the void `InputRouting` was shaped to forbid.
|
|
95
|
+
*
|
|
96
|
+
* In `native-tui` the PTY is the agent's own terminal: writing to it IS the
|
|
97
|
+
* steer, and it has happened by the time the call returns. In `acp` there is no
|
|
98
|
+
* process behind the PTY at all โ it is a render target for the structured
|
|
99
|
+
* stream โ so a write there reaches nobody. The steer has to travel the way
|
|
100
|
+
* every other hostโagent instruction travels, through `turn.steer`, which the
|
|
101
|
+
* caller owns because that is where acknowledgement and idempotency live.
|
|
102
|
+
*
|
|
103
|
+
* So a caller cannot act on the disposition alone: doing the right thing for one
|
|
104
|
+
* mode is either a double-delivery or a dropped keystroke in the other. It has
|
|
105
|
+
* to be told which sink was used.
|
|
106
|
+
*/
|
|
107
|
+
export type InputSink = 'pty' | 'turn.steer' | 'turn.queue';
|
|
108
|
+
export interface InputDelivery {
|
|
109
|
+
/** True when the session has ALREADY put the keystrokes in front of the agent. */
|
|
110
|
+
delivered: boolean;
|
|
111
|
+
sink: InputSink;
|
|
112
|
+
}
|
|
113
|
+
export declare function deliveryFor(mode: SessionRenderMode, routing: InputRouting): InputDelivery;
|
|
114
|
+
export declare function routeHumanInput(context: InputRoutingContext): InputRouting;
|
|
115
|
+
//# sourceMappingURL=sessionMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionMode.d.ts","sourceRoot":"","sources":["../src/sessionMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,CAAA;AAEpD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,0DAA0D;IAC1D,GAAG,EAAE,OAAO,CAAA;CACb;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,EAAE,IAAI,CAAA;IACR,IAAI,EAAE,iBAAiB,CAAA;IACvB,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjC;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,UAAU,CAAC,EAAE,iBAAiB,GAC7B,oBAAoB,CAwCtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,oBAAoB,CAAA;CAAE,GAC1D;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9E,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAA;IACrB;;;8DAG0D;IAC1D,sBAAsB,EAAE,OAAO,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,YAAY,GAAG,YAAY,CAAA;AAE3D,MAAM,WAAW,aAAa;IAC5B,kFAAkF;IAClF,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,GAAG,aAAa,CAKzF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAS1E"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session render mode and input routing โ ADE spec ยง2.8.
|
|
3
|
+
*
|
|
4
|
+
* โ
CONSUMED since 2026-08-13 by `host/session/AgentSessionService`, the ยง2.8
|
|
5
|
+
* substrate these rules were written for. It carried an `@unwired-by-design`
|
|
6
|
+
* marker until that consumer existed; wiring it was the point, so the marker is
|
|
7
|
+
* gone rather than updated.
|
|
8
|
+
*
|
|
9
|
+
* ## 1. The modes are not simultaneous
|
|
10
|
+
*
|
|
11
|
+
* ยง2.8: "The two modes are not simultaneous for one process: a CLI in
|
|
12
|
+
* interactive TUI mode is not also serving ACP. Where an agent supports both,
|
|
13
|
+
* the user switches."
|
|
14
|
+
*
|
|
15
|
+
* So selection returns exactly ONE mode. An agent that supports both is
|
|
16
|
+
* *switchable*, which is a different statement from *running both* โ and a
|
|
17
|
+
* caller handed `{nativeTui: true, acp: true}` would otherwise be free to
|
|
18
|
+
* believe the second one.
|
|
19
|
+
*
|
|
20
|
+
* ## 2. Typing never falls into a void
|
|
21
|
+
*
|
|
22
|
+
* ยง2.8: "Input is routed by the host: mid-turn steering where the agent accepts
|
|
23
|
+
* it, queued as the next turn where it does not. Typing never falls into a void,
|
|
24
|
+
* and human input is always recorded as a human intervention."
|
|
25
|
+
*
|
|
26
|
+
* `InputRouting` has no `drop` case. Not "we decided not to drop input" โ there
|
|
27
|
+
* is no value that means it, so a caller cannot silently discard a keystroke and
|
|
28
|
+
* a future contributor cannot add that path without changing this type. Every
|
|
29
|
+
* outcome is also `recordedAs: 'human-intervention'`, because ยง2.8 says human
|
|
30
|
+
* input is ALWAYS recorded as one, and an unrecorded intervention is a change in
|
|
31
|
+
* the run that the timeline cannot explain.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Chooses the mode a session runs in.
|
|
35
|
+
*
|
|
36
|
+
* ยง2.8: "For a third-party agent with a good TUI, `native-tui` is the default
|
|
37
|
+
* and the right answer. Their interface is the product they built; reproducing
|
|
38
|
+
* it from protocol events yields a worse imitation of something a vendor
|
|
39
|
+
* invested years in, and it rots every time they ship an improvement."
|
|
40
|
+
*
|
|
41
|
+
* An agent supporting neither is a REFUSAL, not a fallback. Quietly picking
|
|
42
|
+
* `acp` for an agent that cannot serve it produces a session that renders
|
|
43
|
+
* nothing and reports no error โ the failure mode where a caller believes it has
|
|
44
|
+
* a working terminal.
|
|
45
|
+
*/
|
|
46
|
+
export function selectSessionRenderMode(support, preference) {
|
|
47
|
+
const switchable = support.nativeTui && support.acp;
|
|
48
|
+
if (!support.nativeTui && !support.acp) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
reason: 'the agent declares neither a native TUI nor ACP, so nothing can render into its session',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (preference) {
|
|
55
|
+
const supported = preference === 'native-tui' ? support.nativeTui : support.acp;
|
|
56
|
+
if (!supported) {
|
|
57
|
+
// Honouring an impossible preference silently would hand back a mode the
|
|
58
|
+
// agent cannot serve; refusing names which half is missing.
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
reason: `the agent does not support ${preference}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
ok: true,
|
|
66
|
+
mode: preference,
|
|
67
|
+
switchable,
|
|
68
|
+
reason: 'explicit user preference',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (support.nativeTui) {
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
mode: 'native-tui',
|
|
75
|
+
switchable,
|
|
76
|
+
reason: "the agent's own TUI is the product its vendor built; rendering it from protocol events would be a worse imitation that rots on every upstream release",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return { ok: true, mode: 'acp', switchable, reason: 'the agent is headless-only' };
|
|
80
|
+
}
|
|
81
|
+
export function deliveryFor(mode, routing) {
|
|
82
|
+
if (routing.disposition === 'queue')
|
|
83
|
+
return { delivered: false, sink: 'turn.queue' };
|
|
84
|
+
return mode === 'native-tui'
|
|
85
|
+
? { delivered: true, sink: 'pty' }
|
|
86
|
+
: { delivered: false, sink: 'turn.steer' };
|
|
87
|
+
}
|
|
88
|
+
export function routeHumanInput(context) {
|
|
89
|
+
if (context.turnInFlight && !context.acceptsMidTurnSteering) {
|
|
90
|
+
return {
|
|
91
|
+
disposition: 'queue',
|
|
92
|
+
recordedAs: 'human-intervention',
|
|
93
|
+
reason: 'the agent does not accept input mid-turn; delivered as the next turn',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return { disposition: 'steer', recordedAs: 'human-intervention' };
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=sessionMode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionMode.js","sourceRoot":"","sources":["../src/sessionMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAuBH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA2B,EAC3B,UAA8B;IAE9B,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAA;IAEnD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACvC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,yFAAyF;SAC5F,CAAA;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,UAAU,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAA;QAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,yEAAyE;YACzE,4DAA4D;YAC5D,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,8BAA8B,UAAU,EAAE;aACnD,CAAA;QACH,CAAC;QACD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,UAAU;YAChB,UAAU;YACV,MAAM,EAAE,0BAA0B;SACnC,CAAA;IACH,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,YAAY;YAClB,UAAU;YACV,MAAM,EACJ,uJAAuJ;SAC1J,CAAA;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAA;AACpF,CAAC;AAgDD,MAAM,UAAU,WAAW,CAAC,IAAuB,EAAE,OAAqB;IACxE,IAAI,OAAO,CAAC,WAAW,KAAK,OAAO;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;IACpF,OAAO,IAAI,KAAK,YAAY;QAC1B,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAA4B;IAC1D,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC;QAC5D,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,UAAU,EAAE,oBAAoB;YAChC,MAAM,EAAE,sEAAsE;SAC/E,CAAA;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAA;AACnE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type WorkspaceSelectionChoice = 'inbox' | 'reuse' | 'create';
|
|
2
|
+
export interface WorkspaceSelectionContinuationInput {
|
|
3
|
+
choice: WorkspaceSelectionChoice;
|
|
4
|
+
directory: string;
|
|
5
|
+
result: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildWorkspaceSelectionContinuationPrompt(input: WorkspaceSelectionContinuationInput): string;
|
|
8
|
+
//# sourceMappingURL=workspaceSelectionContinuation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceSelectionContinuation.d.ts","sourceRoot":"","sources":["../../src/workspace/workspaceSelectionContinuation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEnE,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,wBAAwB,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,mCAAmC,GACzC,MAAM,CAiBR"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function buildWorkspaceSelectionContinuationPrompt(input) {
|
|
2
|
+
const payload = JSON.stringify({
|
|
3
|
+
type: 'workspace_selection.completed',
|
|
4
|
+
status: 'completed',
|
|
5
|
+
choice: input.choice,
|
|
6
|
+
directory: input.directory,
|
|
7
|
+
result: input.result,
|
|
8
|
+
});
|
|
9
|
+
return [
|
|
10
|
+
'This is an internal XENO Hub continuation event, not a new user request.',
|
|
11
|
+
'<xeno_workspace_selection_result>',
|
|
12
|
+
payload,
|
|
13
|
+
'</xeno_workspace_selection_result>',
|
|
14
|
+
'Acknowledge the completed workspace-placement result naturally and briefly.',
|
|
15
|
+
'Do not call tools, ask the user to choose again, repeat the available choices, or restart the original request.',
|
|
16
|
+
].join('\n');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=workspaceSelectionContinuation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceSelectionContinuation.js","sourceRoot":"","sources":["../../src/workspace/workspaceSelectionContinuation.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,yCAAyC,CACvD,KAA0C;IAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,EAAE,+BAA+B;QACrC,MAAM,EAAE,WAAW;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAA;IAEF,OAAO;QACL,0EAA0E;QAC1E,mCAAmC;QACnC,OAAO;QACP,oCAAoC;QACpC,6EAA6E;QAC7E,iHAAiH;KAClH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace knowledge โ ADE ยง5.8 LEARN.
|
|
3
|
+
*
|
|
4
|
+
* The workspace getting better at *this* codebase over time, without the user
|
|
5
|
+
* re-explaining it every session.
|
|
6
|
+
*
|
|
7
|
+
* ## ๐ด The gate is CROSS-PROVIDER, and that is the whole design
|
|
8
|
+
*
|
|
9
|
+
* ยง5.8: *"a fact established in one run is available to a different provider in
|
|
10
|
+
* a later run without the user restating it."*
|
|
11
|
+
*
|
|
12
|
+
* So provenance is RECORDED and never CONSULTED for selection. A fact learned
|
|
13
|
+
* by Claude must reach a GPT run, and an implementation that filtered by
|
|
14
|
+
* provider โ even reasonably, even to avoid "contaminating" a lane โ would pass
|
|
15
|
+
* every test written from the inside and fail the one property the pillar
|
|
16
|
+
* exists for. Selection here does not receive a provider id at all; that is the
|
|
17
|
+
* simplest way to make the mistake unrepresentable.
|
|
18
|
+
*
|
|
19
|
+
* ## Boundary
|
|
20
|
+
*
|
|
21
|
+
* This is *workspace* knowledge โ conventions, architecture, prior decisions.
|
|
22
|
+
* Agent-owned earned memory (the Soul model) belongs to `xeno-anima`. A fact
|
|
23
|
+
* here describes the CODEBASE, not the agent.
|
|
24
|
+
*
|
|
25
|
+
* ## Superseded facts are kept, and not injected
|
|
26
|
+
*
|
|
27
|
+
* "We use npm" then "we moved to pnpm" must not both reach a prompt: an agent
|
|
28
|
+
* given both will pick one at random and be right half the time. The later fact
|
|
29
|
+
* about a subject wins. The earlier one stays in the record, because "when did
|
|
30
|
+
* this change, and who decided?" is a question people actually ask.
|
|
31
|
+
*/
|
|
32
|
+
export interface KnowledgeProvenance {
|
|
33
|
+
/** The run that established it โ so "why does it think that?" is answerable. */
|
|
34
|
+
runId: string;
|
|
35
|
+
/** RECORDED for provenance. Never used to decide what a later run sees. */
|
|
36
|
+
providerId?: string;
|
|
37
|
+
at: number;
|
|
38
|
+
}
|
|
39
|
+
export interface WorkspaceKnowledgeEntry {
|
|
40
|
+
id: string;
|
|
41
|
+
workspaceId: string;
|
|
42
|
+
/**
|
|
43
|
+
* What the fact is ABOUT โ `build.package-manager`, `testing.framework`.
|
|
44
|
+
* Supersession is per subject, so this is what makes "we moved to pnpm"
|
|
45
|
+
* replace "we use npm" rather than sit beside it.
|
|
46
|
+
*/
|
|
47
|
+
subject: string;
|
|
48
|
+
fact: string;
|
|
49
|
+
/**
|
|
50
|
+
* Always included, regardless of budget. For foundational conventions that
|
|
51
|
+
* stop being followed the moment they fall out of a prompt.
|
|
52
|
+
*/
|
|
53
|
+
pinned?: boolean;
|
|
54
|
+
provenance: KnowledgeProvenance;
|
|
55
|
+
}
|
|
56
|
+
export interface KnowledgeSelection {
|
|
57
|
+
/** What should go into the prompt, in the order it should appear. */
|
|
58
|
+
entries: WorkspaceKnowledgeEntry[];
|
|
59
|
+
/** Facts left out for budget. Named, never silently dropped. */
|
|
60
|
+
omitted: Array<{
|
|
61
|
+
subject: string;
|
|
62
|
+
reason: string;
|
|
63
|
+
}>;
|
|
64
|
+
/** Superseded by a later fact about the same subject. Kept for the record. */
|
|
65
|
+
superseded: WorkspaceKnowledgeEntry[];
|
|
66
|
+
/** True when everything current fitted. */
|
|
67
|
+
complete: boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface KnowledgeSelectionOptions {
|
|
70
|
+
/**
|
|
71
|
+
* Rough character budget for the injected block.
|
|
72
|
+
*
|
|
73
|
+
* Characters rather than tokens on purpose: a token count needs a tokenizer
|
|
74
|
+
* per provider, and this must not vary by provider โ see the header. Characters
|
|
75
|
+
* are provider-neutral and wrong by a constant factor, which a caller can size
|
|
76
|
+
* around.
|
|
77
|
+
*/
|
|
78
|
+
maxChars?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Chooses which facts reach a prompt.
|
|
82
|
+
*
|
|
83
|
+
* ๐ด Takes NO provider argument. See the header: the gate is that a fact crosses
|
|
84
|
+
* provider lanes, and a signature that cannot express "filter by provider"
|
|
85
|
+
* cannot accidentally do it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function selectWorkspaceKnowledge(entries: readonly WorkspaceKnowledgeEntry[], options?: KnowledgeSelectionOptions): KnowledgeSelection;
|
|
88
|
+
/** Renders the selection as the block that goes into a prompt. */
|
|
89
|
+
export declare function renderWorkspaceKnowledge(selection: KnowledgeSelection): string;
|
|
90
|
+
//# sourceMappingURL=workspaceKnowledge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceKnowledge.d.ts","sourceRoot":"","sources":["../src/workspaceKnowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,mBAAmB,CAAA;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,OAAO,EAAE,uBAAuB,EAAE,CAAA;IAClC,gEAAgE;IAChE,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnD,8EAA8E;IAC9E,UAAU,EAAE,uBAAuB,EAAE,CAAA;IACrC,2CAA2C;IAC3C,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAID;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,uBAAuB,EAAE,EAC3C,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CAsDpB;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,kBAAkB,GAAG,MAAM,CAS9E"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace knowledge โ ADE ยง5.8 LEARN.
|
|
3
|
+
*
|
|
4
|
+
* The workspace getting better at *this* codebase over time, without the user
|
|
5
|
+
* re-explaining it every session.
|
|
6
|
+
*
|
|
7
|
+
* ## ๐ด The gate is CROSS-PROVIDER, and that is the whole design
|
|
8
|
+
*
|
|
9
|
+
* ยง5.8: *"a fact established in one run is available to a different provider in
|
|
10
|
+
* a later run without the user restating it."*
|
|
11
|
+
*
|
|
12
|
+
* So provenance is RECORDED and never CONSULTED for selection. A fact learned
|
|
13
|
+
* by Claude must reach a GPT run, and an implementation that filtered by
|
|
14
|
+
* provider โ even reasonably, even to avoid "contaminating" a lane โ would pass
|
|
15
|
+
* every test written from the inside and fail the one property the pillar
|
|
16
|
+
* exists for. Selection here does not receive a provider id at all; that is the
|
|
17
|
+
* simplest way to make the mistake unrepresentable.
|
|
18
|
+
*
|
|
19
|
+
* ## Boundary
|
|
20
|
+
*
|
|
21
|
+
* This is *workspace* knowledge โ conventions, architecture, prior decisions.
|
|
22
|
+
* Agent-owned earned memory (the Soul model) belongs to `xeno-anima`. A fact
|
|
23
|
+
* here describes the CODEBASE, not the agent.
|
|
24
|
+
*
|
|
25
|
+
* ## Superseded facts are kept, and not injected
|
|
26
|
+
*
|
|
27
|
+
* "We use npm" then "we moved to pnpm" must not both reach a prompt: an agent
|
|
28
|
+
* given both will pick one at random and be right half the time. The later fact
|
|
29
|
+
* about a subject wins. The earlier one stays in the record, because "when did
|
|
30
|
+
* this change, and who decided?" is a question people actually ask.
|
|
31
|
+
*/
|
|
32
|
+
const DEFAULT_MAX_CHARS = 4_000;
|
|
33
|
+
/**
|
|
34
|
+
* Chooses which facts reach a prompt.
|
|
35
|
+
*
|
|
36
|
+
* ๐ด Takes NO provider argument. See the header: the gate is that a fact crosses
|
|
37
|
+
* provider lanes, and a signature that cannot express "filter by provider"
|
|
38
|
+
* cannot accidentally do it.
|
|
39
|
+
*/
|
|
40
|
+
export function selectWorkspaceKnowledge(entries, options = {}) {
|
|
41
|
+
const maxChars = options.maxChars ?? DEFAULT_MAX_CHARS;
|
|
42
|
+
// Latest per subject wins. Ties go to the later id so the choice is stable
|
|
43
|
+
// rather than dependent on input order.
|
|
44
|
+
const currentBySubject = new Map();
|
|
45
|
+
const superseded = [];
|
|
46
|
+
for (const entry of [...entries].sort((left, right) => left.provenance.at === right.provenance.at
|
|
47
|
+
? left.id.localeCompare(right.id)
|
|
48
|
+
: left.provenance.at - right.provenance.at)) {
|
|
49
|
+
const existing = currentBySubject.get(entry.subject);
|
|
50
|
+
if (existing)
|
|
51
|
+
superseded.push(existing);
|
|
52
|
+
currentBySubject.set(entry.subject, entry);
|
|
53
|
+
}
|
|
54
|
+
const current = [...currentBySubject.values()];
|
|
55
|
+
// Pinned first, then newest. Pinned exists because a foundational convention
|
|
56
|
+
// is usually the OLDEST fact on record, and a pure recency order drops exactly
|
|
57
|
+
// those first โ the conventions stop being followed and nobody knows why.
|
|
58
|
+
const ordered = current.sort((left, right) => {
|
|
59
|
+
if (Boolean(left.pinned) !== Boolean(right.pinned))
|
|
60
|
+
return left.pinned ? -1 : 1;
|
|
61
|
+
return right.provenance.at - left.provenance.at;
|
|
62
|
+
});
|
|
63
|
+
const selected = [];
|
|
64
|
+
const omitted = [];
|
|
65
|
+
let used = 0;
|
|
66
|
+
for (const entry of ordered) {
|
|
67
|
+
const cost = entry.subject.length + entry.fact.length + 2;
|
|
68
|
+
// Pinned bypasses the budget rather than competing for it. A budget that
|
|
69
|
+
// could drop a pinned convention would make `pinned` a suggestion.
|
|
70
|
+
if (entry.pinned || used + cost <= maxChars) {
|
|
71
|
+
selected.push(entry);
|
|
72
|
+
used += cost;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
omitted.push({
|
|
76
|
+
subject: entry.subject,
|
|
77
|
+
reason: 'left out of this prompt for space',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
entries: selected,
|
|
82
|
+
omitted,
|
|
83
|
+
superseded,
|
|
84
|
+
// ๐ด Complete means every CURRENT fact was included. A prompt missing
|
|
85
|
+
// knowledge makes an agent look like it forgot, with nothing on screen to
|
|
86
|
+
// explain why โ so the omission is reported rather than inferred from a
|
|
87
|
+
// shorter block nobody counted.
|
|
88
|
+
complete: omitted.length === 0,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Renders the selection as the block that goes into a prompt. */
|
|
92
|
+
export function renderWorkspaceKnowledge(selection) {
|
|
93
|
+
if (selection.entries.length === 0)
|
|
94
|
+
return '';
|
|
95
|
+
const lines = selection.entries.map((entry) => `- ${entry.subject}: ${entry.fact}`);
|
|
96
|
+
if (!selection.complete) {
|
|
97
|
+
// Stated IN the prompt, not only to the surface: the agent should know its
|
|
98
|
+
// context was trimmed, so it can ask rather than assume.
|
|
99
|
+
lines.push(`- (${selection.omitted.length} further fact(s) omitted for space)`);
|
|
100
|
+
}
|
|
101
|
+
return lines.join('\n');
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=workspaceKnowledge.js.map
|