khala-cli 0.3.0 → 0.4.1
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/README.md +15 -1
- package/dist/{chunk-MGXWUWWP.mjs → chunk-35KKPOKI.mjs} +47 -25
- package/dist/{chunk-ZRUF3P53.mjs → chunk-3SWCRLWX.mjs} +12 -8
- package/dist/chunk-5GLTKWJ5.mjs +1 -0
- package/dist/{chunk-6GOETMWV.mjs → chunk-AVJKIJ34.mjs} +3 -3
- package/dist/{chunk-S6XASSNU.mjs → chunk-B5BFL7OD.mjs} +28 -10
- package/dist/{chunk-525XNG6V.mjs → chunk-CSIFRJFF.mjs} +1 -1
- package/dist/{chunk-CTXFYQIX.mjs → chunk-EVLXC2WS.mjs} +25 -13
- package/dist/{chunk-HMGN52QY.mjs → chunk-HAD5ZILW.mjs} +1 -1
- package/dist/{chunk-4C2TBZVA.mjs → chunk-KEGR6VEQ.mjs} +34 -7
- package/dist/{chunk-UYTGV6TW.mjs → chunk-L2HRDTA5.mjs} +17 -8
- package/dist/{chunk-GO5DD2TR.mjs → chunk-N6LMHR7P.mjs} +16 -3
- package/dist/{chunk-FGIU3YO2.mjs → chunk-PSN7P4AV.mjs} +163 -9
- package/dist/{chunk-HWKLLI7F.mjs → chunk-RX5HGJQT.mjs} +80 -26
- package/dist/{chunk-PQO6675G.mjs → chunk-S72K3GSP.mjs} +70 -5
- package/dist/{chunk-6FNXMYOM.mjs → chunk-SR5BG7FL.mjs} +1 -1
- package/dist/{chunk-H2JCKPFR.mjs → chunk-U5ZMOPUK.mjs} +2 -2
- package/dist/chunk-VUE2DDYY.mjs +34 -0
- package/dist/{chunk-Y3TDVOGT.mjs → chunk-YMDAY234.mjs} +1 -1
- package/dist/khala.mjs +9 -9
- package/dist/web/assets/local-DGdQ2afg.js +9 -0
- package/dist/web/assets/local-DHYvcQG0.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +11 -3
- package/dist/web/assets/local-DuGvSGji.css +0 -1
- package/dist/web/assets/local-hWRGqoWt.js +0 -9
|
@@ -5,14 +5,18 @@ import {
|
|
|
5
5
|
readListeningMode,
|
|
6
6
|
unread,
|
|
7
7
|
writeActivity
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-U5ZMOPUK.mjs";
|
|
9
9
|
import {
|
|
10
10
|
StateError,
|
|
11
11
|
readStatus,
|
|
12
12
|
sessionFiles
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import
|
|
13
|
+
} from "./chunk-B5BFL7OD.mjs";
|
|
14
|
+
import "./chunk-N6LMHR7P.mjs";
|
|
15
|
+
import {
|
|
16
|
+
CURSOR_DEFAULT_SESSION,
|
|
17
|
+
cursorSessionId
|
|
18
|
+
} from "./chunk-VUE2DDYY.mjs";
|
|
19
|
+
import "./chunk-SR5BG7FL.mjs";
|
|
16
20
|
|
|
17
21
|
// hooks/deliver.ts
|
|
18
22
|
import * as fs from "node:fs/promises";
|
|
@@ -79,10 +83,11 @@ async function deliver(stdin, argv, io = {
|
|
|
79
83
|
now: () => /* @__PURE__ */ new Date()
|
|
80
84
|
}) {
|
|
81
85
|
const harness = argv[1];
|
|
82
|
-
if (argv.length !== 2 || argv[0] !== "--harness" || harness !== "claude" && harness !== "codex") {
|
|
86
|
+
if (argv.length !== 2 || argv[0] !== "--harness" || harness !== "claude" && harness !== "codex" && harness !== "cursor") {
|
|
83
87
|
diagnostic(io, "invalid_harness");
|
|
84
88
|
return 0;
|
|
85
89
|
}
|
|
90
|
+
if (harness === "cursor") return deliverCursor(stdin, io);
|
|
86
91
|
let input;
|
|
87
92
|
try {
|
|
88
93
|
input = JSON.parse(stdin);
|
|
@@ -127,9 +132,69 @@ async function deliver(stdin, argv, io = {
|
|
|
127
132
|
}
|
|
128
133
|
return 0;
|
|
129
134
|
}
|
|
135
|
+
var CURSOR_NOOP = { beforeSubmitPrompt: { continue: true }, postToolUse: {}, stop: {} };
|
|
136
|
+
async function cursorFiles(roots, env) {
|
|
137
|
+
const first = Array.isArray(roots) && typeof roots[0] === "string" ? roots[0] : void 0;
|
|
138
|
+
for (const id of /* @__PURE__ */ new Set([cursorSessionId(first), CURSOR_DEFAULT_SESSION])) {
|
|
139
|
+
const files = sessionFiles("cursor", id, env);
|
|
140
|
+
try {
|
|
141
|
+
if ((await fs.stat(files.dir)).isDirectory()) return files;
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
async function deliverCursor(stdin, io) {
|
|
148
|
+
let event;
|
|
149
|
+
let input;
|
|
150
|
+
try {
|
|
151
|
+
input = JSON.parse(stdin.replace(/^/u, ""));
|
|
152
|
+
const name = input?.hook_event_name;
|
|
153
|
+
if (typeof name === "string" && Object.hasOwn(CURSOR_NOOP, name)) event = name;
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
let output = event ? CURSOR_NOOP[event] : {};
|
|
157
|
+
if (event && input) {
|
|
158
|
+
try {
|
|
159
|
+
const files = await cursorFiles(input.workspace_roots, io.env);
|
|
160
|
+
if (files) output = await cursorOutput(files, event, input.loop_count, io) ?? output;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
diagnostic(io, error instanceof StateError ? error.code : "internal_error");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
io.stdout.write(JSON.stringify(output) + "\n");
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
async function cursorOutput(files, event, loopCount, io) {
|
|
172
|
+
const mode = await readListeningMode(files);
|
|
173
|
+
if (event === "beforeSubmitPrompt") {
|
|
174
|
+
await writeActivity(files, "busy", io.now);
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
if (event === "postToolUse" && mode !== "steer") return null;
|
|
178
|
+
if (event === "stop" && (mode === "async" || typeof loopCount === "number" && loopCount > 0)) {
|
|
179
|
+
await writeActivity(files, "idle", io.now);
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const status = await readStatus(files);
|
|
183
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
184
|
+
const { entries, cursor } = await unread(files);
|
|
185
|
+
const { frame, consumed } = selectFrame(status?.channelName, entries);
|
|
186
|
+
if (!frame || !consumed.some(isWakeEntry)) break;
|
|
187
|
+
if (await advanceCursor(files, cursor, consumed) === "conflict") continue;
|
|
188
|
+
await writeActivity(files, "busy", io.now);
|
|
189
|
+
return event === "stop" ? { followup_message: frame } : { additional_context: frame };
|
|
190
|
+
}
|
|
191
|
+
if (event === "stop") await writeActivity(files, "idle", io.now);
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
130
194
|
export {
|
|
131
195
|
run as default,
|
|
132
196
|
deliver,
|
|
197
|
+
deliverCursor,
|
|
133
198
|
renderFrame,
|
|
134
199
|
renderLine
|
|
135
200
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
|
|
3
3
|
// <define:__KHALA_BUNDLE__>
|
|
4
|
-
var define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.
|
|
4
|
+
var define_KHALA_BUNDLE_default = { name: "khala-cli", version: "0.4.1" };
|
|
5
5
|
|
|
6
6
|
export {
|
|
7
7
|
define_KHALA_BUNDLE_default
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
filesForDir,
|
|
5
5
|
readJson,
|
|
6
6
|
writeJsonAtomic
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-B5BFL7OD.mjs";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_LISTENING_MODE,
|
|
10
10
|
decodeChannelEvent,
|
|
11
11
|
decodeListeningMode,
|
|
12
12
|
formatChannelEventLine
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-N6LMHR7P.mjs";
|
|
14
14
|
|
|
15
15
|
// src/inbox.ts
|
|
16
16
|
import * as fs from "node:fs/promises";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// src/cursor.ts
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
var CURSOR_WORKSPACE_ENV = "KHALA_CURSOR_WORKSPACE";
|
|
6
|
+
var CURSOR_DEFAULT_SESSION = "cursor-default";
|
|
7
|
+
function normalizeWorkspace(root) {
|
|
8
|
+
let value = root.trim();
|
|
9
|
+
if (!value || value.includes("${")) return null;
|
|
10
|
+
if (/^file:\/\//iu.test(value)) {
|
|
11
|
+
try {
|
|
12
|
+
value = decodeURIComponent(new URL(value).pathname);
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
value = value.replaceAll("\\", "/");
|
|
18
|
+
if (/^\/[A-Za-z]:(?:\/|$)/u.test(value)) value = value.slice(1);
|
|
19
|
+
if (/^[A-Za-z]:(?:\/|$)/u.test(value)) value = value.toLowerCase();
|
|
20
|
+
value = value.replace(/\/+$/u, "");
|
|
21
|
+
if (/^[a-z]:$/u.test(value)) value += "/";
|
|
22
|
+
return value || null;
|
|
23
|
+
}
|
|
24
|
+
function cursorSessionId(root) {
|
|
25
|
+
const normalized = typeof root === "string" ? normalizeWorkspace(root) : null;
|
|
26
|
+
if (normalized === null) return CURSOR_DEFAULT_SESSION;
|
|
27
|
+
return `ws-${createHash("sha256").update(normalized).digest("hex").slice(0, 32)}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
CURSOR_WORKSPACE_ENV,
|
|
32
|
+
CURSOR_DEFAULT_SESSION,
|
|
33
|
+
cursorSessionId
|
|
34
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
bundle
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HAD5ZILW.mjs";
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
var KHALA_AGENT_VERSION = bundle?.version ?? "0.0.0";
|
package/dist/khala.mjs
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
KHALA_AGENT_VERSION
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-YMDAY234.mjs";
|
|
6
|
+
import "./chunk-HAD5ZILW.mjs";
|
|
7
|
+
import "./chunk-SR5BG7FL.mjs";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
var HOOK_NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
11
11
|
var STDIN_CAP = 1024 * 1024;
|
|
12
|
-
var USAGE = "usage: khala mcp | khala hook <name> | khala local <command> | khala install codex | khala --version";
|
|
12
|
+
var USAGE = "usage: khala mcp | khala hook <name> | khala local <command> | khala install codex | khala install cursor | khala --version";
|
|
13
13
|
async function readStdin() {
|
|
14
14
|
if (process.stdin.isTTY) return "";
|
|
15
15
|
const chunks = [];
|
|
@@ -78,12 +78,12 @@ async function runCli(argv, modules) {
|
|
|
78
78
|
|
|
79
79
|
// src/cli-bundle.ts
|
|
80
80
|
var hooks = {
|
|
81
|
-
deliver: () => import("./chunk-
|
|
82
|
-
"claude-wake": () => import("./chunk-
|
|
81
|
+
deliver: () => import("./chunk-S72K3GSP.mjs"),
|
|
82
|
+
"claude-wake": () => import("./chunk-CSIFRJFF.mjs")
|
|
83
83
|
};
|
|
84
84
|
process.exitCode = await runCli(process.argv.slice(2), {
|
|
85
|
-
mcp: () => () => import("./chunk-
|
|
86
|
-
local: () => () => import("./chunk-
|
|
87
|
-
install: () => () => import("./chunk-
|
|
85
|
+
mcp: () => () => import("./chunk-35KKPOKI.mjs"),
|
|
86
|
+
local: () => () => import("./chunk-RX5HGJQT.mjs"),
|
|
87
|
+
install: () => () => import("./chunk-PSN7P4AV.mjs"),
|
|
88
88
|
hook: (name) => Object.hasOwn(hooks, name) ? hooks[name] : void 0
|
|
89
89
|
});
|