@songsid/agend 2.1.11-beta.1 → 2.1.11-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/kiro-engine-ledger.d.ts +36 -0
- package/dist/backend/kiro-engine-ledger.js +113 -0
- package/dist/backend/kiro-engine-ledger.js.map +1 -0
- package/dist/backend/kiro-kas-store.d.ts +11 -0
- package/dist/backend/kiro-kas-store.js +67 -0
- package/dist/backend/kiro-kas-store.js.map +1 -0
- package/dist/backend/kiro-v3-identity.d.ts +28 -0
- package/dist/backend/kiro-v3-identity.js +213 -0
- package/dist/backend/kiro-v3-identity.js.map +1 -0
- package/dist/backend/kiro.d.ts +7 -0
- package/dist/backend/kiro.js +34 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode-permission.d.ts +49 -0
- package/dist/backend/opencode-permission.js +181 -0
- package/dist/backend/opencode-permission.js.map +1 -0
- package/dist/backend/opencode.d.ts +6 -0
- package/dist/backend/opencode.js +46 -2
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +15 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.js +26 -25
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/ipc-bridge.d.ts +1 -0
- package/dist/channel/ipc-bridge.js +1 -1
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-tools.js +2 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/command-table.d.ts +99 -0
- package/dist/command-table.js +125 -0
- package/dist/command-table.js.map +1 -0
- package/dist/daemon.d.ts +36 -0
- package/dist/daemon.js +165 -2
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +16 -0
- package/dist/delivery-outbox.js +55 -6
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/e2e-isolation.d.ts +122 -0
- package/dist/e2e-isolation.js +386 -0
- package/dist/e2e-isolation.js.map +1 -0
- package/dist/fleet-manager.d.ts +24 -0
- package/dist/fleet-manager.js +292 -484
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +56 -0
- package/dist/instance-lifecycle.d.ts +2 -0
- package/dist/instance-lifecycle.js +14 -0
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/kiro-engine-status.d.ts +71 -0
- package/dist/kiro-engine-status.js +68 -0
- package/dist/kiro-engine-status.js.map +1 -0
- package/dist/locale.js +10 -0
- package/dist/locale.js.map +1 -1
- package/dist/login-flows.js +10 -0
- package/dist/login-flows.js.map +1 -1
- package/dist/outbound-handlers.js +16 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +3 -0
- package/dist/outbound-schemas.js +3 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/paths.d.ts +19 -0
- package/dist/paths.js +18 -5
- package/dist/paths.js.map +1 -1
- package/dist/tool-permissions.js +4 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/ui/web-terminal/terminal-input.js +69 -0
- package/dist/ui/web-terminal/terminal.css +6 -0
- package/dist/ui/web-terminal/terminal.html +9 -1
- package/dist/ui/web-terminal/terminal.js +31 -2
- package/dist/web-terminal-http.js +1 -0
- package/dist/web-terminal-http.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type KiroUi = "legacy" | "tui" | "v3";
|
|
2
|
+
export interface KiroLaunchRecord {
|
|
3
|
+
at: string;
|
|
4
|
+
kiroVersion: string | null;
|
|
5
|
+
agendVersion: string;
|
|
6
|
+
ui: KiroUi;
|
|
7
|
+
flags: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface KiroLedgerEntry {
|
|
10
|
+
workingDirectory: string;
|
|
11
|
+
/** The credential profile the instance launched under; null for the shared store. */
|
|
12
|
+
credentialProfile: string | null;
|
|
13
|
+
firstSeen: string;
|
|
14
|
+
lastLaunch: KiroLaunchRecord;
|
|
15
|
+
/** One row per change of kiro version, AgEnD version, UI or engine flags; newest last. */
|
|
16
|
+
history: KiroLaunchRecord[];
|
|
17
|
+
}
|
|
18
|
+
export type KiroLedger = Record<string, KiroLedgerEntry>;
|
|
19
|
+
export declare function kiroLedgerPath(agendHome?: string): string;
|
|
20
|
+
export declare function agendVersion(): string;
|
|
21
|
+
export declare function readKiroLedger(path?: string): KiroLedger;
|
|
22
|
+
/** Write via a temp file and rename; the temp file is removed whatever happens. Throws on failure. */
|
|
23
|
+
export declare function writeFileAtomic(path: string, data: string): void;
|
|
24
|
+
/** Read, change one entry, write back atomically. Returns false when the ledger could not be written. */
|
|
25
|
+
export declare function updateKiroLedger(instance: string, change: (entry: KiroLedgerEntry | undefined) => KiroLedgerEntry | undefined, path?: string): boolean;
|
|
26
|
+
export interface KiroLaunchFacts {
|
|
27
|
+
instance: string;
|
|
28
|
+
workingDirectory: string;
|
|
29
|
+
credentialProfile: string | null;
|
|
30
|
+
kiroVersion: string | null;
|
|
31
|
+
ui: KiroUi;
|
|
32
|
+
/** The UI/engine flags AgEnD pinned for this launch. */
|
|
33
|
+
flags: string[];
|
|
34
|
+
now?: Date;
|
|
35
|
+
}
|
|
36
|
+
export declare function recordKiroLaunch(facts: KiroLaunchFacts, path?: string): boolean;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which kiro engine, kiro-cli version and AgEnD version each kiro instance
|
|
3
|
+
* has been launched with — the baseline the V1 → V3 migration works from.
|
|
4
|
+
*
|
|
5
|
+
* Kept in `<AGEND_HOME>/kiro-engine-ledger.json`, not the instance directory:
|
|
6
|
+
* `replace_instance` deletes that directory, and the migration needs to know
|
|
7
|
+
* what an instance ran on before it was replaced.
|
|
8
|
+
*
|
|
9
|
+
* It is a record, not a source of truth: writing it is best-effort, and a
|
|
10
|
+
* launch never fails because it could not be read or written. Which V3
|
|
11
|
+
* session an instance owns is NOT kept here (see kiro-v3-identity.ts), since
|
|
12
|
+
* that has to be durable and exclusive and this does not.
|
|
13
|
+
*/
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { randomBytes } from "node:crypto";
|
|
18
|
+
import { getAgendHome } from "../paths.js";
|
|
19
|
+
const HISTORY_LIMIT = 20;
|
|
20
|
+
export function kiroLedgerPath(agendHome = getAgendHome()) {
|
|
21
|
+
return join(agendHome, "kiro-engine-ledger.json");
|
|
22
|
+
}
|
|
23
|
+
let agendVersionCache;
|
|
24
|
+
export function agendVersion() {
|
|
25
|
+
if (agendVersionCache === undefined) {
|
|
26
|
+
try {
|
|
27
|
+
agendVersionCache = String(createRequire(import.meta.url)("../../package.json").version ?? "unknown");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
agendVersionCache = "unknown";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return agendVersionCache;
|
|
34
|
+
}
|
|
35
|
+
const isObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
36
|
+
const UIS = ["legacy", "tui", "v3"];
|
|
37
|
+
function isLaunchRecord(v) {
|
|
38
|
+
return isObject(v) && typeof v.at === "string"
|
|
39
|
+
&& (v.kiroVersion === null || typeof v.kiroVersion === "string")
|
|
40
|
+
&& typeof v.agendVersion === "string" && UIS.includes(v.ui)
|
|
41
|
+
&& Array.isArray(v.flags) && v.flags.every(f => typeof f === "string");
|
|
42
|
+
}
|
|
43
|
+
/** An entry the code can read without guessing, down to every launch record; anything else is dropped. */
|
|
44
|
+
function isLedgerEntry(v) {
|
|
45
|
+
return isObject(v) && typeof v.workingDirectory === "string" && typeof v.firstSeen === "string"
|
|
46
|
+
&& (v.credentialProfile === null || typeof v.credentialProfile === "string")
|
|
47
|
+
&& isLaunchRecord(v.lastLaunch) && Array.isArray(v.history) && v.history.every(isLaunchRecord);
|
|
48
|
+
}
|
|
49
|
+
export function readKiroLedger(path = kiroLedgerPath()) {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
52
|
+
if (isObject(parsed))
|
|
53
|
+
return Object.fromEntries(Object.entries(parsed).filter(([, e]) => isLedgerEntry(e)));
|
|
54
|
+
}
|
|
55
|
+
catch { /* missing or damaged: start over */ }
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
/** Write via a temp file and rename; the temp file is removed whatever happens. Throws on failure. */
|
|
59
|
+
export function writeFileAtomic(path, data) {
|
|
60
|
+
const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
|
|
61
|
+
try {
|
|
62
|
+
writeFileSync(tmp, data, { mode: 0o600, flag: "wx" });
|
|
63
|
+
renameSync(tmp, path);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
rmSync(tmp, { force: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function writeKiroLedger(ledger, path) {
|
|
70
|
+
writeFileAtomic(path, JSON.stringify(ledger, null, 2) + "\n");
|
|
71
|
+
}
|
|
72
|
+
/** Read, change one entry, write back atomically. Returns false when the ledger could not be written. */
|
|
73
|
+
export function updateKiroLedger(instance, change, path = kiroLedgerPath()) {
|
|
74
|
+
try {
|
|
75
|
+
const ledger = readKiroLedger(path);
|
|
76
|
+
const next = change(ledger[instance]);
|
|
77
|
+
if (next === undefined)
|
|
78
|
+
return true;
|
|
79
|
+
ledger[instance] = next;
|
|
80
|
+
writeKiroLedger(ledger, path);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function sameLaunch(a, b) {
|
|
88
|
+
return a.kiroVersion === b.kiroVersion && a.agendVersion === b.agendVersion && a.ui === b.ui
|
|
89
|
+
&& a.flags.length === b.flags.length && a.flags.every((f, i) => f === b.flags[i]);
|
|
90
|
+
}
|
|
91
|
+
export function recordKiroLaunch(facts, path = kiroLedgerPath()) {
|
|
92
|
+
const record = {
|
|
93
|
+
at: (facts.now ?? new Date()).toISOString(),
|
|
94
|
+
kiroVersion: facts.kiroVersion,
|
|
95
|
+
agendVersion: agendVersion(),
|
|
96
|
+
ui: facts.ui,
|
|
97
|
+
flags: [...facts.flags],
|
|
98
|
+
};
|
|
99
|
+
return updateKiroLedger(facts.instance, entry => {
|
|
100
|
+
const history = entry?.history ?? [];
|
|
101
|
+
const last = history[history.length - 1];
|
|
102
|
+
const nextHistory = last && sameLaunch(last, record) ? history : [...history, record].slice(-HISTORY_LIMIT);
|
|
103
|
+
return {
|
|
104
|
+
...entry,
|
|
105
|
+
workingDirectory: facts.workingDirectory,
|
|
106
|
+
credentialProfile: facts.credentialProfile,
|
|
107
|
+
firstSeen: entry?.firstSeen ?? record.at,
|
|
108
|
+
lastLaunch: record,
|
|
109
|
+
history: nextHistory,
|
|
110
|
+
};
|
|
111
|
+
}, path);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=kiro-engine-ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kiro-engine-ledger.js","sourceRoot":"","sources":["../../src/backend/kiro-engine-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface KasSession {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Epoch ms from session.json, or null when absent or not a time. */
|
|
4
|
+
createdAt: number | null;
|
|
5
|
+
lastModifiedAt: number | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function kiroHome(env?: NodeJS.ProcessEnv): string;
|
|
8
|
+
/** The bucket kiro files a working directory's V3 sessions under. */
|
|
9
|
+
export declare function kasBucket(workingDirectory: string): string;
|
|
10
|
+
/** This working directory's V3 sessions, most recently active first. Unreadable entries are skipped. */
|
|
11
|
+
export declare function listKasSessions(workingDirectory: string, env?: NodeJS.ProcessEnv): KasSession[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kiro's V3 (KAS) session store, read-only.
|
|
3
|
+
*
|
|
4
|
+
* V3 keeps a conversation as a directory, not a sqlite row:
|
|
5
|
+
* <KIRO_HOME or ~/.kiro>/sessions/<bucket>/<session id>/{session.json, messages.jsonl}
|
|
6
|
+
* where <bucket> is the first 16 hex of SHA-256 of the working directory
|
|
7
|
+
* (checked against real buckets kiro-cli 2.27.1 wrote). Session ids are
|
|
8
|
+
* `sess_<uuid>` for sessions V3 started and `cli_<classic id>_<suffix>` for ones
|
|
9
|
+
* converted from a classic conversation.
|
|
10
|
+
*
|
|
11
|
+
* Unlike the classic store this is not under XDG_DATA_HOME, so a credential
|
|
12
|
+
* profile does not give an instance its own copy of it.
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
import { readdirSync, readFileSync, realpathSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
/** A timestamp kiro wrote, as an instant; anything that is not one is null (never "" or NaN). */
|
|
19
|
+
function instant(v) {
|
|
20
|
+
if (typeof v !== "string")
|
|
21
|
+
return null;
|
|
22
|
+
const ms = Date.parse(v);
|
|
23
|
+
return Number.isFinite(ms) ? ms : null;
|
|
24
|
+
}
|
|
25
|
+
export function kiroHome(env = process.env) {
|
|
26
|
+
return env.KIRO_HOME || join(homedir(), ".kiro");
|
|
27
|
+
}
|
|
28
|
+
/** The bucket kiro files a working directory's V3 sessions under. */
|
|
29
|
+
export function kasBucket(workingDirectory) {
|
|
30
|
+
let cwd = workingDirectory;
|
|
31
|
+
// kiro hashes its process cwd, which the kernel reports with symlinks resolved.
|
|
32
|
+
try {
|
|
33
|
+
cwd = realpathSync(workingDirectory);
|
|
34
|
+
}
|
|
35
|
+
catch { /* not there (yet): hash it as given */ }
|
|
36
|
+
return createHash("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
37
|
+
}
|
|
38
|
+
/** This working directory's V3 sessions, most recently active first. Unreadable entries are skipped. */
|
|
39
|
+
export function listKasSessions(workingDirectory, env = process.env) {
|
|
40
|
+
const dir = join(kiroHome(env), "sessions", kasBucket(workingDirectory));
|
|
41
|
+
let names;
|
|
42
|
+
try {
|
|
43
|
+
names = readdirSync(dir);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const sessions = [];
|
|
49
|
+
for (const name of names) {
|
|
50
|
+
if (name.startsWith("."))
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
const meta = JSON.parse(readFileSync(join(dir, name, "session.json"), "utf8"));
|
|
54
|
+
// The directory name is the id `--resume-id` takes (what ensure-session returns).
|
|
55
|
+
sessions.push({
|
|
56
|
+
id: name,
|
|
57
|
+
createdAt: instant(meta.createdAt),
|
|
58
|
+
lastModifiedAt: instant(meta.lastModifiedAt),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch { /* not a session directory, or one being written */ }
|
|
62
|
+
}
|
|
63
|
+
// Compared as instants (offsets differ between writers); one with no time sorts last.
|
|
64
|
+
const latest = (s) => s.lastModifiedAt ?? s.createdAt ?? -Infinity;
|
|
65
|
+
return sessions.sort((a, b) => latest(b) - latest(a));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=kiro-kas-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kiro-kas-store.js","sourceRoot":"","sources":["../../src/backend/kiro-kas-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,iGAAiG;AACjG,SAAS,OAAO,CAAC,CAAU;IACzB,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC3D,OAAO,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,SAAS,CAAC,gBAAwB;IAChD,IAAI,GAAG,GAAG,gBAAgB,CAAC;IAC3B,gFAAgF;IAChF,IAAI,CAAC;QAAC,GAAG,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,uCAAuC,CAAC,CAAC;IAC/F,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,eAAe,CAAC,gBAAwB,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC5F,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACzE,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QAAC,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IACtD,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAA4B,CAAC;YAC1G,kFAAkF;YAClF,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,IAAI;gBACR,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;gBAClC,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC;aAC7C,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC,CAAC,mDAAmD,CAAC,CAAC;IACjE,CAAC;IACD,sFAAsF;IACtF,MAAM,MAAM,GAAG,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,QAAQ,CAAC;IAC/E,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** The fresh start could not be recorded: launching anyway would let the next launch resume what this one gave up. */
|
|
2
|
+
export declare class KiroV3IdentityError extends Error {
|
|
3
|
+
constructor(detail: string);
|
|
4
|
+
}
|
|
5
|
+
export interface KiroV3ResumeOptions {
|
|
6
|
+
/** Start fresh: give up the session this instance owned. */
|
|
7
|
+
skipResume?: boolean;
|
|
8
|
+
agendHome?: string;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
now?: Date;
|
|
11
|
+
}
|
|
12
|
+
export declare function resolveKiroV3Resume(instance: string, workingDirectory: string, credentialProfile: string | null, opts?: KiroV3ResumeOptions): string | null;
|
|
13
|
+
export type KiroV3Identity = {
|
|
14
|
+
kind: "none";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "unreadable";
|
|
17
|
+
} | {
|
|
18
|
+
kind: "owned";
|
|
19
|
+
id: string;
|
|
20
|
+
claimHeld: boolean;
|
|
21
|
+
credentialProfile: string | null;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "fresh";
|
|
24
|
+
since: string;
|
|
25
|
+
credentialProfile: string | null;
|
|
26
|
+
};
|
|
27
|
+
/** What an instance's V3 identity says right now, read-only (for kiro_engine_status). */
|
|
28
|
+
export declare function readKiroV3Identity(instance: string, agendHome?: string): KiroV3Identity;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which V3 session a V3 kiro instance owns, and so resumes.
|
|
3
|
+
*
|
|
4
|
+
* Kiro's V3 `--resume` takes the newest conversation in the working directory
|
|
5
|
+
* from ANY engine, and converts a classic one into a new V3 copy on every
|
|
6
|
+
* launch (#1141 kiro migration study). A V3 instance therefore resumes by id —
|
|
7
|
+
* and the id must be its own: never a sibling's running conversation, never
|
|
8
|
+
* one it gave up, never a guess. Two stores, both under `<AGEND_HOME>/kiro-v3`:
|
|
9
|
+
*
|
|
10
|
+
* claims/<session id> created exclusively ("wx") holding the owner's name
|
|
11
|
+
* and a newline, the newline written last: a claim
|
|
12
|
+
* without it is still being written (or was cut
|
|
13
|
+
* short) and belongs to nobody who can use it.
|
|
14
|
+
* Whoever created it owns the session; nobody else
|
|
15
|
+
* can take it over, and only the owner removes it.
|
|
16
|
+
* instances/<name>.json the instance's state, written only by its own
|
|
17
|
+
* launch: the session it owns, or a fresh-start mark
|
|
18
|
+
* (`id: null`, when, and which sessions already existed).
|
|
19
|
+
*
|
|
20
|
+
* A session is taken up only with evidence that this instance's own fresh
|
|
21
|
+
* launch made it: created (a valid instant) after the mark, absent from the
|
|
22
|
+
* mark's list, owned by nobody, and the only such session — with no other
|
|
23
|
+
* instance in the same directory waiting to take up its own. Anything less
|
|
24
|
+
* certain starts fresh again — and a fresh start is only made once it is
|
|
25
|
+
* on record: one that cannot be recorded refuses the launch, since the next
|
|
26
|
+
* launch would otherwise go back to the session this one gave up. Two V3
|
|
27
|
+
* instances in one working directory
|
|
28
|
+
* cannot tell their sessions apart and each keeps starting fresh: a known
|
|
29
|
+
* limit, chosen over handing one of them the other's conversation.
|
|
30
|
+
*/
|
|
31
|
+
import { mkdirSync, openSync, closeSync, readdirSync, readFileSync, rmSync, writeSync } from "node:fs";
|
|
32
|
+
import { join } from "node:path";
|
|
33
|
+
import { getAgendHome } from "../paths.js";
|
|
34
|
+
import { writeFileAtomic } from "./kiro-engine-ledger.js";
|
|
35
|
+
import { kasBucket, listKasSessions } from "./kiro-kas-store.js";
|
|
36
|
+
/** Session ids and instance names become file names: only plain ones. */
|
|
37
|
+
const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,199}$/;
|
|
38
|
+
/** Never a valid instance name (it fails SAFE_NAME), so never mistaken for one. */
|
|
39
|
+
const INCOMPLETE = "\0incomplete";
|
|
40
|
+
function isState(v) {
|
|
41
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
42
|
+
return false;
|
|
43
|
+
const s = v;
|
|
44
|
+
return typeof s.bucket === "string"
|
|
45
|
+
&& (s.credentialProfile === null || typeof s.credentialProfile === "string")
|
|
46
|
+
&& (s.id === null || (typeof s.id === "string" && SAFE_NAME.test(s.id)))
|
|
47
|
+
// A real instant: Date accepts only ±8.64e15 ms, and an out-of-range mark is no evidence of anything.
|
|
48
|
+
&& typeof s.since === "number" && Number.isFinite(new Date(s.since).getTime())
|
|
49
|
+
&& Array.isArray(s.known) && s.known.every(k => typeof k === "string");
|
|
50
|
+
}
|
|
51
|
+
/** The fresh start could not be recorded: launching anyway would let the next launch resume what this one gave up. */
|
|
52
|
+
export class KiroV3IdentityError extends Error {
|
|
53
|
+
constructor(detail) {
|
|
54
|
+
super(`AgEnD could not record this V3 instance's fresh start (${detail}); not launching, so the conversation it gave up is not resumed later`);
|
|
55
|
+
this.name = "KiroV3IdentityError";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function resolveKiroV3Resume(instance, workingDirectory, credentialProfile, opts = {}) {
|
|
59
|
+
if (!SAFE_NAME.test(instance))
|
|
60
|
+
return null;
|
|
61
|
+
const root = join(opts.agendHome ?? getAgendHome(), "kiro-v3");
|
|
62
|
+
const claims = join(root, "claims");
|
|
63
|
+
const instances = join(root, "instances");
|
|
64
|
+
const statePath = join(instances, `${instance}.json`);
|
|
65
|
+
const bucket = kasBucket(workingDirectory);
|
|
66
|
+
const sessions = listKasSessions(workingDirectory, opts.env).filter(s => SAFE_NAME.test(s.id));
|
|
67
|
+
const readState = (path) => {
|
|
68
|
+
try {
|
|
69
|
+
const v = JSON.parse(readFileSync(path, "utf8"));
|
|
70
|
+
return isState(v) ? v : null;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/** null: unclaimed. INCOMPLETE: a claim being written, or cut short — someone's, and not usable. */
|
|
77
|
+
const owner = (id) => {
|
|
78
|
+
let text;
|
|
79
|
+
try {
|
|
80
|
+
text = readFileSync(join(claims, id), "utf8");
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return err.code === "ENOENT" ? null : INCOMPLETE;
|
|
84
|
+
}
|
|
85
|
+
return text.endsWith("\n") ? text.slice(0, -1) : INCOMPLETE;
|
|
86
|
+
};
|
|
87
|
+
/** Claims an unclaimed session. True only once the whole owner line is on disk. */
|
|
88
|
+
const claim = (id) => {
|
|
89
|
+
const path = join(claims, id);
|
|
90
|
+
let fd;
|
|
91
|
+
try {
|
|
92
|
+
mkdirSync(claims, { recursive: true, mode: 0o700 });
|
|
93
|
+
fd = openSync(path, "wx", 0o600);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
let complete = false;
|
|
99
|
+
try {
|
|
100
|
+
const line = Buffer.from(`${instance}\n`);
|
|
101
|
+
let offset = 0;
|
|
102
|
+
while (offset < line.length) {
|
|
103
|
+
const n = writeSync(fd, line, offset, line.length - offset);
|
|
104
|
+
if (n <= 0)
|
|
105
|
+
break;
|
|
106
|
+
offset += n;
|
|
107
|
+
}
|
|
108
|
+
complete = offset === line.length;
|
|
109
|
+
}
|
|
110
|
+
catch { /* the claim stays incomplete */ }
|
|
111
|
+
finally {
|
|
112
|
+
closeSync(fd);
|
|
113
|
+
}
|
|
114
|
+
// Ours (created exclusively), so ours to take back when it could not be finished.
|
|
115
|
+
if (!complete)
|
|
116
|
+
rmSync(path, { force: true });
|
|
117
|
+
return complete;
|
|
118
|
+
};
|
|
119
|
+
// Only the owner removes a claim, and no one can create it while it exists, so read-then-remove is safe.
|
|
120
|
+
const release = (id) => { if (owner(id) === instance)
|
|
121
|
+
rmSync(join(claims, id), { force: true }); };
|
|
122
|
+
const writeState = (state) => {
|
|
123
|
+
try {
|
|
124
|
+
mkdirSync(instances, { recursive: true, mode: 0o700 });
|
|
125
|
+
writeFileAtomic(statePath, JSON.stringify(state) + "\n");
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const state = readState(statePath);
|
|
133
|
+
const startFresh = () => {
|
|
134
|
+
// Recorded first: until it is, the old state still says which session this instance holds.
|
|
135
|
+
if (!writeState({ bucket, credentialProfile, id: null, since: (opts.now ?? new Date()).getTime(), known: sessions.map(s => s.id) })) {
|
|
136
|
+
throw new KiroV3IdentityError(`cannot write ${statePath}`);
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
if (state?.id)
|
|
140
|
+
release(state.id);
|
|
141
|
+
}
|
|
142
|
+
catch { /* the claim stays; it only keeps others off a session nobody resumes */ }
|
|
143
|
+
return null;
|
|
144
|
+
};
|
|
145
|
+
if (opts.skipResume || !state || state.bucket !== bucket || state.credentialProfile !== credentialProfile)
|
|
146
|
+
return startFresh();
|
|
147
|
+
if (state.id) {
|
|
148
|
+
const id = state.id;
|
|
149
|
+
// Resumed only while the claim is really held: a state alone never re-creates one.
|
|
150
|
+
return sessions.some(s => s.id === id) && owner(id) === instance ? id : startFresh();
|
|
151
|
+
}
|
|
152
|
+
// A fresh start is on record: take up the session that launch made, if — and only if — that is certain.
|
|
153
|
+
const known = new Set(state.known);
|
|
154
|
+
const candidates = sessions.filter(s => !known.has(s.id) && s.createdAt !== null && s.createdAt > state.since
|
|
155
|
+
&& (owner(s.id) ?? instance) === instance);
|
|
156
|
+
const siblingWaiting = (() => {
|
|
157
|
+
let names;
|
|
158
|
+
// Siblings that cannot be listed are siblings that cannot be ruled out.
|
|
159
|
+
try {
|
|
160
|
+
names = readdirSync(instances);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return names.some(n => {
|
|
166
|
+
if (n === `${instance}.json` || !n.endsWith(".json"))
|
|
167
|
+
return false;
|
|
168
|
+
const other = readState(join(instances, n));
|
|
169
|
+
// An unreadable state in this directory could be a sibling waiting: not certain, so it counts.
|
|
170
|
+
return other === null || (other.bucket === bucket && other.id === null);
|
|
171
|
+
});
|
|
172
|
+
})();
|
|
173
|
+
if (candidates.length !== 1 || siblingWaiting)
|
|
174
|
+
return startFresh();
|
|
175
|
+
const pick = candidates[0].id;
|
|
176
|
+
// Already ours when an earlier launch claimed it but could not record that in its state.
|
|
177
|
+
if (owner(pick) !== instance && !claim(pick))
|
|
178
|
+
return startFresh();
|
|
179
|
+
// The claim is the ownership; if the state cannot record it, the next launch finds the claim again.
|
|
180
|
+
writeState({ ...state, id: pick });
|
|
181
|
+
return pick;
|
|
182
|
+
}
|
|
183
|
+
/** What an instance's V3 identity says right now, read-only (for kiro_engine_status). */
|
|
184
|
+
export function readKiroV3Identity(instance, agendHome = getAgendHome()) {
|
|
185
|
+
if (!SAFE_NAME.test(instance))
|
|
186
|
+
return { kind: "none" };
|
|
187
|
+
const root = join(agendHome, "kiro-v3");
|
|
188
|
+
let raw;
|
|
189
|
+
try {
|
|
190
|
+
raw = readFileSync(join(root, "instances", `${instance}.json`), "utf8");
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
return err.code === "ENOENT" ? { kind: "none" } : { kind: "unreadable" };
|
|
194
|
+
}
|
|
195
|
+
let state;
|
|
196
|
+
try {
|
|
197
|
+
state = JSON.parse(raw);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return { kind: "unreadable" };
|
|
201
|
+
}
|
|
202
|
+
if (!isState(state))
|
|
203
|
+
return { kind: "unreadable" };
|
|
204
|
+
if (state.id === null)
|
|
205
|
+
return { kind: "fresh", since: new Date(state.since).toISOString(), credentialProfile: state.credentialProfile };
|
|
206
|
+
let claimHeld = false;
|
|
207
|
+
try {
|
|
208
|
+
claimHeld = readFileSync(join(root, "claims", state.id), "utf8") === `${instance}\n`;
|
|
209
|
+
}
|
|
210
|
+
catch { /* not held */ }
|
|
211
|
+
return { kind: "owned", id: state.id, claimHeld, credentialProfile: state.credentialProfile };
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=kiro-v3-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kiro-v3-identity.js","sourceRoot":"","sources":["../../src/backend/kiro-v3-identity.ts"],"names":[],"mappings":"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"}
|
package/dist/backend/kiro.d.ts
CHANGED
|
@@ -89,6 +89,13 @@ export declare function planKiroLaunch(ui: "legacy" | "tui" | "v3", compat: Kiro
|
|
|
89
89
|
export declare function getCachedKiroCliCompatibility(binaryPath: string, run?: KiroProbeRunner): KiroCliCompatibility;
|
|
90
90
|
/** Test-only reset for the process-level compatibility and warning memo. */
|
|
91
91
|
export declare function resetKiroCompatibilityCacheForTests(): void;
|
|
92
|
+
/** The kiro-cli compatibility AgEnD last probed for a launch: read by kiro_engine_status, which never probes itself. */
|
|
93
|
+
export interface KiroCompatibilitySnapshot {
|
|
94
|
+
binaryPath: string;
|
|
95
|
+
compatibility: KiroCliCompatibility;
|
|
96
|
+
at: string;
|
|
97
|
+
}
|
|
98
|
+
export declare function lastKiroCompatibilitySnapshot(): KiroCompatibilitySnapshot | null;
|
|
92
99
|
/** Startup budget for a `--resume` launch (60% first output, 40% ready). */
|
|
93
100
|
export declare const KIRO_RESUME_STARTUP_BUDGET_MS = 60000;
|
|
94
101
|
export declare class KiroBackend implements CliBackend {
|
package/dist/backend/kiro.js
CHANGED
|
@@ -8,6 +8,8 @@ import { UnsupportedCliError, resolveBinary, shellQuote, validateEffort, validat
|
|
|
8
8
|
import { PIE_CLASS } from "../tui-glyphs.js";
|
|
9
9
|
import { KIRO_EXPIRED_LOGIN_SCREEN } from "../login-flows.js";
|
|
10
10
|
import { t } from "../locale.js";
|
|
11
|
+
import { recordKiroLaunch } from "./kiro-engine-ledger.js";
|
|
12
|
+
import { resolveKiroV3Resume } from "./kiro-v3-identity.js";
|
|
11
13
|
// Kiro CLI feature gates. These are deliberately separate: the flags shipped
|
|
12
14
|
// in different releases, so one broad "old Kiro" check would still crash some
|
|
13
15
|
// supported versions with an unknown argument. Every row below was read from
|
|
@@ -485,6 +487,13 @@ export function resetKiroCompatibilityCacheForTests() {
|
|
|
485
487
|
warnedUnsupportedEffortCacheKeys.clear();
|
|
486
488
|
warnedVersionGateCacheKeys.clear();
|
|
487
489
|
}
|
|
490
|
+
let lastKiroCompatibility = null;
|
|
491
|
+
export function lastKiroCompatibilitySnapshot() {
|
|
492
|
+
return lastKiroCompatibility;
|
|
493
|
+
}
|
|
494
|
+
function publishKiroCompatibility(binaryPath, compatibility) {
|
|
495
|
+
lastKiroCompatibility = { binaryPath, compatibility, at: new Date().toISOString() };
|
|
496
|
+
}
|
|
488
497
|
/** Startup budget for a `--resume` launch (60% first output, 40% ready). */
|
|
489
498
|
export const KIRO_RESUME_STARTUP_BUDGET_MS = 60_000;
|
|
490
499
|
export class KiroBackend {
|
|
@@ -524,6 +533,7 @@ export class KiroBackend {
|
|
|
524
533
|
const cached = cachedKiroCliCompatibility(this.binaryPath);
|
|
525
534
|
this.compatibility = cached.compatibility;
|
|
526
535
|
this.compatibilityCacheKey = cached.cacheKey;
|
|
536
|
+
publishKiroCompatibility(this.binaryPath, this.compatibility);
|
|
527
537
|
}
|
|
528
538
|
}
|
|
529
539
|
requiresDeliveryEnterRetry() {
|
|
@@ -604,6 +614,8 @@ export class KiroBackend {
|
|
|
604
614
|
this.compatibility = current.compatibility;
|
|
605
615
|
this.compatibilityCacheKey = current.cacheKey;
|
|
606
616
|
}
|
|
617
|
+
// What this launch is judged by, for kiro_engine_status to read without probing.
|
|
618
|
+
publishKiroCompatibility(this.binaryPath, this.compatibility);
|
|
607
619
|
if (this.compatibility.source === "unknown") {
|
|
608
620
|
// Neither --version nor chat --help answered: a missing or wedged binary,
|
|
609
621
|
// or a loaded host timing out. Launching blind could start kiro on its
|
|
@@ -617,6 +629,15 @@ export class KiroBackend {
|
|
|
617
629
|
for (const flag of plan.flags)
|
|
618
630
|
cmd += ` ${flag}`;
|
|
619
631
|
this.noteVersionGate();
|
|
632
|
+
const credentialProfile = resolveCredentialProfile(config.backendOptions);
|
|
633
|
+
recordKiroLaunch({
|
|
634
|
+
instance: config.instanceName,
|
|
635
|
+
workingDirectory: config.workingDirectory,
|
|
636
|
+
credentialProfile,
|
|
637
|
+
kiroVersion: this.compatibility.version ?? null,
|
|
638
|
+
ui,
|
|
639
|
+
flags: plan.flags,
|
|
640
|
+
});
|
|
620
641
|
// Record what is actually being launched for the delivery gate (see
|
|
621
642
|
// dropsEnterWhileBusy): the legacy prompt row exists only under
|
|
622
643
|
// --legacy-ui; a binary from before 1.27 paints its own classic screen.
|
|
@@ -636,8 +657,20 @@ export class KiroBackend {
|
|
|
636
657
|
// store, which is the same thing every brand-new instance does on its first
|
|
637
658
|
// launch. Switching profiles also skips resume outright (crash-state
|
|
638
659
|
// resumeDisabled), so this never fires against a store that just changed.
|
|
639
|
-
|
|
660
|
+
//
|
|
661
|
+
// V3 is the exception, and resumes only the session it owns, by id: its
|
|
662
|
+
// `--resume` takes the newest conversation in the directory from ANY
|
|
663
|
+
// engine and converts a classic one into a new V3 copy — on every launch.
|
|
664
|
+
// A skipped resume is recorded there too, so the session given up is not
|
|
665
|
+
// taken back on the next launch. See kiro-v3-identity.ts.
|
|
666
|
+
if (ui === "v3") {
|
|
667
|
+
const id = resolveKiroV3Resume(config.instanceName, config.workingDirectory, credentialProfile, { skipResume: config.skipResume });
|
|
668
|
+
if (id)
|
|
669
|
+
cmd += ` --resume-id ${shellQuote(id)}`;
|
|
670
|
+
}
|
|
671
|
+
else if (!config.skipResume) {
|
|
640
672
|
cmd += " --resume";
|
|
673
|
+
}
|
|
641
674
|
if (config.model) {
|
|
642
675
|
const model = validateModel(config.model);
|
|
643
676
|
warnIfModelMismatch("kiro-cli", model);
|