@agentclientprotocol/claude-agent-acp 0.88.1-preview.6 → 0.89.0
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/dist/acp-agent.d.ts +26 -1
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +91 -17
- package/dist/air-extension.d.ts +23 -0
- package/dist/air-extension.d.ts.map +1 -1
- package/dist/air-extension.js +23 -0
- package/dist/diff.d.ts +2 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +37 -1
- package/dist/mcp-command.d.ts.map +1 -1
- package/dist/mcp-command.js +5 -0
- package/dist/session-index/activity.d.ts +56 -0
- package/dist/session-index/activity.d.ts.map +1 -0
- package/dist/session-index/activity.js +96 -0
- package/dist/session-index/archive-title.d.ts +52 -0
- package/dist/session-index/archive-title.d.ts.map +1 -0
- package/dist/session-index/archive-title.js +77 -0
- package/dist/session-index/connection.d.ts +152 -0
- package/dist/session-index/connection.d.ts.map +1 -0
- package/dist/session-index/connection.js +310 -0
- package/dist/session-index/dir-listing.d.ts +30 -0
- package/dist/session-index/dir-listing.d.ts.map +1 -0
- package/dist/session-index/dir-listing.js +110 -0
- package/dist/session-index/explicit-title.d.ts +34 -0
- package/dist/session-index/explicit-title.d.ts.map +1 -0
- package/dist/session-index/explicit-title.js +65 -0
- package/dist/session-index/first-prompt.d.ts +37 -0
- package/dist/session-index/first-prompt.d.ts.map +1 -0
- package/dist/session-index/first-prompt.js +195 -0
- package/dist/session-index/list-subscriptions.d.ts +190 -0
- package/dist/session-index/list-subscriptions.d.ts.map +1 -0
- package/dist/session-index/list-subscriptions.js +1163 -0
- package/dist/session-index/live-registry.d.ts +72 -0
- package/dist/session-index/live-registry.d.ts.map +1 -0
- package/dist/session-index/live-registry.js +240 -0
- package/dist/session-index/project-dirs.d.ts +45 -0
- package/dist/session-index/project-dirs.d.ts.map +1 -0
- package/dist/session-index/project-dirs.js +122 -0
- package/dist/session-index/service.d.ts +158 -0
- package/dist/session-index/service.d.ts.map +1 -0
- package/dist/session-index/service.js +546 -0
- package/dist/session-index/session-index.d.ts +201 -0
- package/dist/session-index/session-index.d.ts.map +1 -0
- package/dist/session-index/session-index.js +740 -0
- package/dist/session-index/session-info.d.ts +16 -0
- package/dist/session-index/session-info.d.ts.map +1 -0
- package/dist/session-index/session-info.js +51 -0
- package/dist/session-index/transcript-scan.d.ts +137 -0
- package/dist/session-index/transcript-scan.d.ts.map +1 -0
- package/dist/session-index/transcript-scan.js +545 -0
- package/dist/session-index/worktrees.d.ts +25 -0
- package/dist/session-index/worktrees.d.ts.map +1 -0
- package/dist/session-index/worktrees.js +128 -0
- package/dist/session-titles.d.ts +21 -0
- package/dist/session-titles.d.ts.map +1 -1
- package/dist/session-titles.js +101 -5
- package/dist/utils.d.ts +31 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +60 -2
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/session-index/activity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;gEAE4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AA+BF,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,eAAe,GAAG,SAAS,CAqC9B;AAED;;eAEe;AACf,wBAAgB,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG/E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `activity` and `cost` of a session list row.
|
|
3
|
+
*
|
|
4
|
+
* A session that this connection runs reports the SDK's own state, and
|
|
5
|
+
* `error` when it is idle and its last turn failed with an error (not a
|
|
6
|
+
* cancel). Another session reports what the CLI registry and the transcript
|
|
7
|
+
* tell:
|
|
8
|
+
*
|
|
9
|
+
* - no live process holds it: `idle`, or `error` when its last turn ended
|
|
10
|
+
* with an API error;
|
|
11
|
+
* - an interactive CLI that is not driven by an SDK holds it, and its registry
|
|
12
|
+
* status is newer than the transcript: the registry status (an idle one is
|
|
13
|
+
* `error` after such a turn);
|
|
14
|
+
* - otherwise the transcript tail: a finished turn is `idle` (`error` after
|
|
15
|
+
* an API error), an unfinished turn written in the last 10 minutes is
|
|
16
|
+
* `running`, and anything else has no known state.
|
|
17
|
+
*
|
|
18
|
+
* A user interrupt is no error. A new turn clears it.
|
|
19
|
+
*
|
|
20
|
+
* The SDK-driven CLIs (`entrypoint: sdk-*`, which includes the ones this
|
|
21
|
+
* adapter starts) keep `busy` in the registry long after a turn ends, so their
|
|
22
|
+
* registry status is not used.
|
|
23
|
+
*/
|
|
24
|
+
const RECENT_UNFINISHED_TURN_MS = 10 * 60 * 1000;
|
|
25
|
+
function registryState(status) {
|
|
26
|
+
switch (status) {
|
|
27
|
+
case "busy":
|
|
28
|
+
case "shell":
|
|
29
|
+
return "running";
|
|
30
|
+
case "waiting":
|
|
31
|
+
return "requires_action";
|
|
32
|
+
case "idle":
|
|
33
|
+
return "idle";
|
|
34
|
+
default:
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function usesRegistryStatus(record, transcriptMtimeMs) {
|
|
39
|
+
return (record.kind === "interactive" &&
|
|
40
|
+
!(record.entrypoint ?? "").startsWith("sdk-") &&
|
|
41
|
+
record.statusUpdatedAt !== undefined &&
|
|
42
|
+
record.statusUpdatedAt > transcriptMtimeMs);
|
|
43
|
+
}
|
|
44
|
+
function iso(ms) {
|
|
45
|
+
return ms === undefined || !Number.isFinite(ms) ? undefined : new Date(ms).toISOString();
|
|
46
|
+
}
|
|
47
|
+
export function deriveActivity(input) {
|
|
48
|
+
const { live, facts, transcriptMtimeMs, now } = input;
|
|
49
|
+
const failedAt = input.own?.queryFailedAt;
|
|
50
|
+
const own = failedAt === undefined ? input.own : undefined;
|
|
51
|
+
let state;
|
|
52
|
+
// A finished turn that ended with an API error, or this connection's query
|
|
53
|
+
// of the session failed and nothing was written since.
|
|
54
|
+
const failed = (facts.turnState === "finished" && facts.lastTurnError === true) ||
|
|
55
|
+
(failedAt !== undefined &&
|
|
56
|
+
!((facts.lastPromptAt ?? 0) > failedAt) &&
|
|
57
|
+
!((facts.lastTurnEndedAt ?? 0) > failedAt));
|
|
58
|
+
if (own) {
|
|
59
|
+
state = own.state ?? "idle";
|
|
60
|
+
if (state === "idle" && own.lastTurnFailed)
|
|
61
|
+
state = "error";
|
|
62
|
+
}
|
|
63
|
+
else if (!live) {
|
|
64
|
+
state = failed ? "error" : "idle";
|
|
65
|
+
}
|
|
66
|
+
else if (usesRegistryStatus(live, transcriptMtimeMs)) {
|
|
67
|
+
// A busy or waiting CLI wins; an idle one shows how its turn ended.
|
|
68
|
+
state = registryState(live.status);
|
|
69
|
+
if (state === "idle" && failed)
|
|
70
|
+
state = "error";
|
|
71
|
+
}
|
|
72
|
+
else if (failed) {
|
|
73
|
+
state = "error";
|
|
74
|
+
}
|
|
75
|
+
else if (facts.turnState === "finished") {
|
|
76
|
+
state = "idle";
|
|
77
|
+
}
|
|
78
|
+
else if (facts.turnState === "unfinished" &&
|
|
79
|
+
now - transcriptMtimeMs < RECENT_UNFINISHED_TURN_MS) {
|
|
80
|
+
state = "running";
|
|
81
|
+
}
|
|
82
|
+
const lastTurnEndedAt = iso(own?.lastTurnEndedAt ?? facts.lastTurnEndedAt);
|
|
83
|
+
if (state === undefined && lastTurnEndedAt === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
return {
|
|
86
|
+
...(state !== undefined && { state }),
|
|
87
|
+
...(lastTurnEndedAt !== undefined && { lastTurnEndedAt }),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** The cost of a session this connection runs: the `total_cost_usd` the SDK
|
|
91
|
+
* gave in its last result. Only a positive amount; none for any other
|
|
92
|
+
* session. */
|
|
93
|
+
export function selectCost(own) {
|
|
94
|
+
const amount = own?.costUsd;
|
|
95
|
+
return amount !== undefined && Number.isFinite(amount) && amount > 0 ? amount : undefined;
|
|
96
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session archive, in the on-disk format of JetBrains AIR's own Claude
|
|
3
|
+
* integration: a session is archived when its title carries the
|
|
4
|
+
* `[archived] ` prefix, and archive, unarchive and rename append the title as
|
|
5
|
+
* a pair of records to the transcript:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* {"type":"custom-title","customTitle":"[archived] Title","sessionId":"…"}
|
|
9
|
+
* {"type":"agent-name","agentName":"[archived] Title","sessionId":"…"}
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The archive state follows AIR's native Claude provider (see
|
|
13
|
+
* {@link effectiveTitle}): the last agent name decides, else the custom title
|
|
14
|
+
* the SDK reports (`SDKSessionInfo.customTitle`). Archive writes the prefix
|
|
15
|
+
* and the current title without it; unarchive writes the title without the
|
|
16
|
+
* prefix. Both are cut to the CLI's 200-character title limit. The records
|
|
17
|
+
* are metadata: they move neither `updatedAt` nor the list order. The
|
|
18
|
+
* `claude --resume` picker shows the prefix.
|
|
19
|
+
*/
|
|
20
|
+
/** The title prefix of an archived session. */
|
|
21
|
+
export declare const ARCHIVED_TITLE_PREFIX = "[archived] ";
|
|
22
|
+
/** Whitespace collapsed to single spaces and trimmed, as AIR stores a title. */
|
|
23
|
+
export declare function normalizeStoredTitle(title: string): string;
|
|
24
|
+
/** Whether a session name (see {@link effectiveTitle}) marks its session
|
|
25
|
+
* archived. */
|
|
26
|
+
export declare function isArchivedTitle(title: string | undefined): boolean;
|
|
27
|
+
/** The title shown for a stored title: without the archive prefix,
|
|
28
|
+
* removed once, as AIR shows it. */
|
|
29
|
+
export declare function visibleTitle(title: string): string;
|
|
30
|
+
/** The title of a session that has none at all, as AIR names it. */
|
|
31
|
+
export declare function defaultSessionTitle(sessionId: string): string;
|
|
32
|
+
/** The title that `title` is stored as in the given archive state: the
|
|
33
|
+
* visible title, with the prefix when archived, normalized and cut to the
|
|
34
|
+
* CLI limit. */
|
|
35
|
+
export declare function storedTitle(title: string, archived: boolean, sessionId: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* The title of a session and its archive state, by the rule of AIR's native
|
|
38
|
+
* Claude provider: the session's name is its last agent name, else its custom
|
|
39
|
+
* title, and the session is archived exactly when that name starts with the
|
|
40
|
+
* prefix. The title is that agent name, else `summary`, the title the SDK
|
|
41
|
+
* gives the session; it is stored, so it may carry the prefix.
|
|
42
|
+
*/
|
|
43
|
+
export declare function effectiveTitle(agentName: string | undefined, { customTitle, summary }: {
|
|
44
|
+
customTitle?: string;
|
|
45
|
+
summary?: string;
|
|
46
|
+
}): {
|
|
47
|
+
title: string | undefined;
|
|
48
|
+
archived: boolean;
|
|
49
|
+
};
|
|
50
|
+
/** The `custom-title` and `agent-name` records of `title`, one per line. */
|
|
51
|
+
export declare function titleRecords(sessionId: string, title: string): string;
|
|
52
|
+
//# sourceMappingURL=archive-title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-title.d.ts","sourceRoot":"","sources":["../../src/session-index/archive-title.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAenD,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAOD;gBACgB;AAChB,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAElE;AAED;qCACqC;AACrC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;iBAEiB;AACjB,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKvF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAElD;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session archive, in the on-disk format of JetBrains AIR's own Claude
|
|
3
|
+
* integration: a session is archived when its title carries the
|
|
4
|
+
* `[archived] ` prefix, and archive, unarchive and rename append the title as
|
|
5
|
+
* a pair of records to the transcript:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* {"type":"custom-title","customTitle":"[archived] Title","sessionId":"…"}
|
|
9
|
+
* {"type":"agent-name","agentName":"[archived] Title","sessionId":"…"}
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The archive state follows AIR's native Claude provider (see
|
|
13
|
+
* {@link effectiveTitle}): the last agent name decides, else the custom title
|
|
14
|
+
* the SDK reports (`SDKSessionInfo.customTitle`). Archive writes the prefix
|
|
15
|
+
* and the current title without it; unarchive writes the title without the
|
|
16
|
+
* prefix. Both are cut to the CLI's 200-character title limit. The records
|
|
17
|
+
* are metadata: they move neither `updatedAt` nor the list order. The
|
|
18
|
+
* `claude --resume` picker shows the prefix.
|
|
19
|
+
*/
|
|
20
|
+
/** The title prefix of an archived session. */
|
|
21
|
+
export const ARCHIVED_TITLE_PREFIX = "[archived] ";
|
|
22
|
+
/** What the CLI keeps of a stored title: `title.slice(0, 200).trim()`. */
|
|
23
|
+
const CLI_TITLE_LIMIT = 200;
|
|
24
|
+
/** A title once normalized starts with the prefix: leading space (what a
|
|
25
|
+
* trim removes), the marker, a run of white space, then a title character.
|
|
26
|
+
* The white space AIR collapses is ASCII white space, as in Java's `\s`. */
|
|
27
|
+
const ARCHIVED_PATTERN = /^\s*\[archived\][ \t\n\v\f\r]+(?=[^ \t\n\v\f\r])/;
|
|
28
|
+
/** Every leading archive prefix at once. */
|
|
29
|
+
const ARCHIVED_PREFIXES = /^(?:\s*\[archived\][ \t\n\v\f\r]+(?=[^ \t\n\v\f\r]))+/;
|
|
30
|
+
const WHITESPACE_RUN = /[ \t\n\v\f\r]+/g;
|
|
31
|
+
/** Whitespace collapsed to single spaces and trimmed, as AIR stores a title. */
|
|
32
|
+
export function normalizeStoredTitle(title) {
|
|
33
|
+
return title.replace(WHITESPACE_RUN, " ").trim();
|
|
34
|
+
}
|
|
35
|
+
/** Cut to what the CLI keeps of a title. */
|
|
36
|
+
function capTitle(title) {
|
|
37
|
+
return title.length <= CLI_TITLE_LIMIT ? title : title.slice(0, CLI_TITLE_LIMIT).trim();
|
|
38
|
+
}
|
|
39
|
+
/** Whether a session name (see {@link effectiveTitle}) marks its session
|
|
40
|
+
* archived. */
|
|
41
|
+
export function isArchivedTitle(title) {
|
|
42
|
+
return title !== undefined && ARCHIVED_PATTERN.test(title);
|
|
43
|
+
}
|
|
44
|
+
/** The title shown for a stored title: without the archive prefix,
|
|
45
|
+
* removed once, as AIR shows it. */
|
|
46
|
+
export function visibleTitle(title) {
|
|
47
|
+
return title.replace(ARCHIVED_PATTERN, "");
|
|
48
|
+
}
|
|
49
|
+
/** The title of a session that has none at all, as AIR names it. */
|
|
50
|
+
export function defaultSessionTitle(sessionId) {
|
|
51
|
+
return `Session ${sessionId.slice(0, 8)}`;
|
|
52
|
+
}
|
|
53
|
+
/** The title that `title` is stored as in the given archive state: the
|
|
54
|
+
* visible title, with the prefix when archived, normalized and cut to the
|
|
55
|
+
* CLI limit. */
|
|
56
|
+
export function storedTitle(title, archived, sessionId) {
|
|
57
|
+
// Every prefix: a title stored twice prefixed must not stay archived.
|
|
58
|
+
const visible = normalizeStoredTitle(title.replace(ARCHIVED_PREFIXES, "")) || defaultSessionTitle(sessionId);
|
|
59
|
+
return capTitle(archived ? ARCHIVED_TITLE_PREFIX + visible : visible);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The title of a session and its archive state, by the rule of AIR's native
|
|
63
|
+
* Claude provider: the session's name is its last agent name, else its custom
|
|
64
|
+
* title, and the session is archived exactly when that name starts with the
|
|
65
|
+
* prefix. The title is that agent name, else `summary`, the title the SDK
|
|
66
|
+
* gives the session; it is stored, so it may carry the prefix.
|
|
67
|
+
*/
|
|
68
|
+
export function effectiveTitle(agentName, { customTitle, summary }) {
|
|
69
|
+
return { title: agentName ?? summary, archived: isArchivedTitle(agentName ?? customTitle) };
|
|
70
|
+
}
|
|
71
|
+
/** The `custom-title` and `agent-name` records of `title`, one per line. */
|
|
72
|
+
export function titleRecords(sessionId, title) {
|
|
73
|
+
return (JSON.stringify({ type: "custom-title", customTitle: title, sessionId }) +
|
|
74
|
+
"\n" +
|
|
75
|
+
JSON.stringify({ type: "agent-name", agentName: title, sessionId }) +
|
|
76
|
+
"\n");
|
|
77
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session index of one ACP connection: what `ClaudeAcpAgent` does for a
|
|
3
|
+
* client that declared `sessionIndex`, and the archive of an AIR client
|
|
4
|
+
* without it. The agent keeps thin call sites; everything else
|
|
5
|
+
* lives here.
|
|
6
|
+
*
|
|
7
|
+
* Wire contract: docs/air-extensions.md, "Session index".
|
|
8
|
+
*/
|
|
9
|
+
import { type AgentApp, type DeleteSessionRequest, type DeleteSessionResponse, type InitializeRequest, type ListSessionsRequest, type ListSessionsResponse } from "@agentclientprotocol/sdk";
|
|
10
|
+
import type { AcpClient, Logger, Session } from "../acp-agent.js";
|
|
11
|
+
import { type ListSubscribeRequest, type ListSubscribeResponse, type ListUnsubscribeRequest } from "./list-subscriptions.js";
|
|
12
|
+
import { SessionIndexService, type RenameSessionRequest, type SessionIdRequest } from "./service.js";
|
|
13
|
+
/** What the session index keeps on each `Session`. */
|
|
14
|
+
export type SessionIndexFields = {
|
|
15
|
+
/** When the last turn ended (the last `session_state_changed: idle`), epoch
|
|
16
|
+
* ms. Reported as `lastTurnEndedAt` in the session index. */
|
|
17
|
+
lastTurnEndedAt?: number;
|
|
18
|
+
/** The last turn failed with an error, not a cancel; a new turn clears
|
|
19
|
+
* it. Reported as the `error` state in the session index. */
|
|
20
|
+
lastTurnFailed?: boolean;
|
|
21
|
+
/** `total_cost_usd` of the last result, reported as the cost of the session
|
|
22
|
+
* in the session index. */
|
|
23
|
+
lastTotalCostUsd?: number;
|
|
24
|
+
/** The query resumed a stored conversation (load, resume, fork): the
|
|
25
|
+
* session has a transcript, unlike a new one before its first turn. */
|
|
26
|
+
resumedFromHistory?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** Records the end of a turn at `session_state_changed`. */
|
|
29
|
+
export declare function noteSessionState(session: Session, previous: Session["lastSessionState"], state: Session["lastSessionState"]): void;
|
|
30
|
+
/** What the connection needs from the agent. */
|
|
31
|
+
export type SessionIndexHost = {
|
|
32
|
+
/** Read when used: the agent may still be under construction. */
|
|
33
|
+
agent: {
|
|
34
|
+
readonly sessions: {
|
|
35
|
+
[key: string]: Session;
|
|
36
|
+
};
|
|
37
|
+
readonly client: AcpClient;
|
|
38
|
+
readonly logger: Logger;
|
|
39
|
+
};
|
|
40
|
+
/** Whether the client is an AIR client. */
|
|
41
|
+
isAirClient(): boolean;
|
|
42
|
+
/** Cancels the running turns of a session loaded here and sends its CLI
|
|
43
|
+
* the interrupt, without awaiting the reply. */
|
|
44
|
+
interruptSession(sessionId: string): Promise<void>;
|
|
45
|
+
/** Closes a session loaded here, as `session/close` does. */
|
|
46
|
+
teardownSession(sessionId: string): Promise<void>;
|
|
47
|
+
};
|
|
48
|
+
type EmptyResponse = Record<string, never>;
|
|
49
|
+
export declare class SessionIndexConnection {
|
|
50
|
+
private readonly host;
|
|
51
|
+
/**
|
|
52
|
+
* The session index of a client that declared `sessionIndex`. Undefined for
|
|
53
|
+
* every other client, which keeps the session list, delete and the watchers
|
|
54
|
+
* exactly as before.
|
|
55
|
+
*/
|
|
56
|
+
service?: SessionIndexService;
|
|
57
|
+
/** The archive behind `session/delete` of an AIR client without
|
|
58
|
+
* `sessionIndex`: the same writes, without a list or a watcher. */
|
|
59
|
+
private archiver?;
|
|
60
|
+
/** When the query of a session failed here, by session id. */
|
|
61
|
+
private readonly failedQueries;
|
|
62
|
+
constructor(host: SessionIndexHost);
|
|
63
|
+
/** Sets the index up for the client of `initialize`. ACP v2 does not route
|
|
64
|
+
* the session index methods yet. */
|
|
65
|
+
negotiate(request: InitializeRequest, options: {
|
|
66
|
+
v2: boolean;
|
|
67
|
+
}): void;
|
|
68
|
+
/** A stored title as the client shows it: an AIR client gets the title
|
|
69
|
+
* of an archived session without the archive prefix, as in its list;
|
|
70
|
+
* every other client the title as stored. */
|
|
71
|
+
clientTitle(title: string): string;
|
|
72
|
+
/** The AIR capabilities the agent advertises for the index: the index
|
|
73
|
+
* itself, archive, rename and the list subscription, all only to a client
|
|
74
|
+
* that declared `sessionIndex`. */
|
|
75
|
+
capabilities(): string[];
|
|
76
|
+
dispose(): void;
|
|
77
|
+
/** The query of a session that ran here failed (not a cancel): its row
|
|
78
|
+
* shows `error` until its transcript changes. */
|
|
79
|
+
onQueryFailed(sessionId: string): void;
|
|
80
|
+
/** A turn of a session started here: an earlier failed query of it no
|
|
81
|
+
* longer counts. */
|
|
82
|
+
onTurnStarted(sessionId: string): void;
|
|
83
|
+
onTeardown(sessionId: string): void;
|
|
84
|
+
/** A session this connection runs changed its state, turn end or cost:
|
|
85
|
+
* the list subscriptions send it at once. */
|
|
86
|
+
onOwnSessionChanged(sessionId: string): void;
|
|
87
|
+
/** `_session/list/subscribe`. */
|
|
88
|
+
subscribeList(params: ListSubscribeRequest): Promise<ListSubscribeResponse>;
|
|
89
|
+
/** `_session/list/unsubscribe`. Idempotent. */
|
|
90
|
+
unsubscribeList(params: ListUnsubscribeRequest): EmptyResponse;
|
|
91
|
+
/** `session/list` of a `sessionIndex` client; undefined for another one. */
|
|
92
|
+
list(params: ListSessionsRequest): Promise<ListSessionsResponse> | undefined;
|
|
93
|
+
/** An AIR client archives with session/delete (see {@link deleteSession}):
|
|
94
|
+
* its archived sessions (an archived custom title) stay hidden from the
|
|
95
|
+
* old list, as when the delete removed them. */
|
|
96
|
+
hideArchived<T extends {
|
|
97
|
+
customTitle?: string;
|
|
98
|
+
}>(sessions: T[]): T[];
|
|
99
|
+
/** `_session/rename`: names a session; no generated title replaces it.
|
|
100
|
+
* An archived session stays archived. */
|
|
101
|
+
rename(request: RenameSessionRequest): Promise<EmptyResponse>;
|
|
102
|
+
/** `_session/archive`: hides a session from the default list and stops
|
|
103
|
+
* it. Idempotent; the session need not be loaded. A session loaded here
|
|
104
|
+
* is interrupted, retitled through its CLI while that still runs, then
|
|
105
|
+
* closed as `session/close` closes it. */
|
|
106
|
+
archive(params: SessionIdRequest): Promise<EmptyResponse>;
|
|
107
|
+
/** `_session/unarchive`. Idempotent; it does not load the session. */
|
|
108
|
+
unarchive(params: SessionIdRequest): Promise<EmptyResponse>;
|
|
109
|
+
/**
|
|
110
|
+
* Retitles a session (see {@link SessionIndexService.retitle}). A session
|
|
111
|
+
* this connection runs is titled through its CLI (`rename_session`). A
|
|
112
|
+
* loaded session's title state takes the change as a client title, so no
|
|
113
|
+
* generated title replaces it; `publish` is the title it then publishes.
|
|
114
|
+
*/
|
|
115
|
+
private retitle;
|
|
116
|
+
/**
|
|
117
|
+
* `session/delete`:
|
|
118
|
+
* - A `sessionIndex` client deletes for real: every transcript, whoever
|
|
119
|
+
* else has the session open, as the CLI does.
|
|
120
|
+
* - Another AIR client uses delete to mark a session done, and may reopen
|
|
121
|
+
* it later: the adapter archives it instead (as `_session/archive` does,
|
|
122
|
+
* after the CLI closed), so the transcript survives.
|
|
123
|
+
* - Every other client: the SDK delete, as before.
|
|
124
|
+
*/
|
|
125
|
+
deleteSession(params: DeleteSessionRequest): Promise<DeleteSessionResponse>;
|
|
126
|
+
private airArchiver;
|
|
127
|
+
private requireService;
|
|
128
|
+
/** What the session index reports for a session this connection runs. */
|
|
129
|
+
private ownSessionState;
|
|
130
|
+
/** A new session this connection runs that may have no transcript yet: it
|
|
131
|
+
* resumed no stored conversation and no turn of it has ended. A session
|
|
132
|
+
* whose query ended, or that has history, needs its transcript. */
|
|
133
|
+
private isUnwrittenSession;
|
|
134
|
+
/** Tells the client the archive state of a session that was loaded on
|
|
135
|
+
* this connection (`session_info_update` with
|
|
136
|
+
* `_meta.jetbrains.air.archived`, RFD #2161's `archived` field), also
|
|
137
|
+
* once the archive closed it. */
|
|
138
|
+
private reportArchived;
|
|
139
|
+
}
|
|
140
|
+
/** The agent methods behind the session index extension methods. */
|
|
141
|
+
type SessionIndexMethods = {
|
|
142
|
+
subscribeSessionList(params: ListSubscribeRequest): Promise<ListSubscribeResponse>;
|
|
143
|
+
unsubscribeSessionList(params: ListUnsubscribeRequest): Promise<EmptyResponse>;
|
|
144
|
+
renameSessionTitle(params: RenameSessionRequest): Promise<EmptyResponse>;
|
|
145
|
+
archiveSession(params: SessionIdRequest): Promise<EmptyResponse>;
|
|
146
|
+
unarchiveSession(params: SessionIdRequest): Promise<EmptyResponse>;
|
|
147
|
+
};
|
|
148
|
+
/** Routes `_session/list/subscribe`, `_session/list/unsubscribe`,
|
|
149
|
+
* `_session/rename`, `_session/archive` and `_session/unarchive`. */
|
|
150
|
+
export declare function onSessionIndexRequests(app: AgentApp, agent: () => SessionIndexMethods): AgentApp;
|
|
151
|
+
export {};
|
|
152
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/session-index/connection.ts"],"names":[],"mappings":"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"}
|