@duetso/agent 0.1.202 → 0.2.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.
Files changed (66) hide show
  1. package/README.md +3 -6
  2. package/dist/package.json +1 -1
  3. package/dist/src/cli/help.d.ts.map +1 -1
  4. package/dist/src/cli/help.js +15 -21
  5. package/dist/src/cli/help.js.map +1 -1
  6. package/dist/src/cli/login.d.ts +2 -3
  7. package/dist/src/cli/login.d.ts.map +1 -1
  8. package/dist/src/cli/login.js +17 -32
  9. package/dist/src/cli/login.js.map +1 -1
  10. package/dist/src/cli/model-gateway.d.ts +3 -3
  11. package/dist/src/cli/model-gateway.js +3 -3
  12. package/dist/src/cli/rpc.d.ts +0 -2
  13. package/dist/src/cli/rpc.d.ts.map +1 -1
  14. package/dist/src/cli/rpc.js +1 -16
  15. package/dist/src/cli/rpc.js.map +1 -1
  16. package/dist/src/cli/run.d.ts.map +1 -1
  17. package/dist/src/cli/run.js +1 -15
  18. package/dist/src/cli/run.js.map +1 -1
  19. package/dist/src/cli/send-feedback.d.ts +1 -1
  20. package/dist/src/cli/send-feedback.js +1 -1
  21. package/dist/src/cli/train.js +1 -1
  22. package/dist/src/cli/train.js.map +1 -1
  23. package/dist/src/lib/duet-api-url.d.ts +9 -0
  24. package/dist/src/lib/duet-api-url.d.ts.map +1 -0
  25. package/dist/src/lib/duet-api-url.js +18 -0
  26. package/dist/src/lib/duet-api-url.js.map +1 -0
  27. package/dist/src/lib/feedback.d.ts +1 -1
  28. package/dist/src/lib/feedback.js +4 -4
  29. package/dist/src/lib/feedback.js.map +1 -1
  30. package/dist/src/lib/login.d.ts +24 -21
  31. package/dist/src/lib/login.d.ts.map +1 -1
  32. package/dist/src/lib/login.js +50 -114
  33. package/dist/src/lib/login.js.map +1 -1
  34. package/dist/src/memory/embedding.d.ts +20 -15
  35. package/dist/src/memory/embedding.d.ts.map +1 -1
  36. package/dist/src/memory/embedding.js +26 -20
  37. package/dist/src/memory/embedding.js.map +1 -1
  38. package/dist/src/model-resolution/duet-gateway.d.ts +4 -3
  39. package/dist/src/model-resolution/duet-gateway.d.ts.map +1 -1
  40. package/dist/src/model-resolution/duet-gateway.js +12 -6
  41. package/dist/src/model-resolution/duet-gateway.js.map +1 -1
  42. package/dist/src/tui/step-renderer.d.ts +4 -0
  43. package/dist/src/tui/step-renderer.d.ts.map +1 -1
  44. package/dist/src/tui/step-renderer.js +41 -37
  45. package/dist/src/tui/step-renderer.js.map +1 -1
  46. package/dist/src/tui/tool-formatters.d.ts +2 -2
  47. package/dist/src/tui/tool-formatters.d.ts.map +1 -1
  48. package/dist/src/turn-runner/agent-events.d.ts +12 -1
  49. package/dist/src/turn-runner/agent-events.d.ts.map +1 -1
  50. package/dist/src/turn-runner/agent-events.js +60 -42
  51. package/dist/src/turn-runner/agent-events.js.map +1 -1
  52. package/dist/src/turn-runner/turn-runner.d.ts +2 -0
  53. package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
  54. package/dist/src/turn-runner/turn-runner.js +4 -2
  55. package/dist/src/turn-runner/turn-runner.js.map +1 -1
  56. package/dist/src/types/protocol.d.ts +22 -3
  57. package/dist/src/types/protocol.d.ts.map +1 -1
  58. package/package.json +1 -1
  59. package/dist/src/lib/duet-app-url.d.ts +0 -10
  60. package/dist/src/lib/duet-app-url.d.ts.map +0 -1
  61. package/dist/src/lib/duet-app-url.js +0 -19
  62. package/dist/src/lib/duet-app-url.js.map +0 -1
  63. package/dist/src/lib/sync-skills.d.ts +0 -54
  64. package/dist/src/lib/sync-skills.d.ts.map +0 -1
  65. package/dist/src/lib/sync-skills.js +0 -215
  66. package/dist/src/lib/sync-skills.js.map +0 -1
@@ -1,215 +0,0 @@
1
- import { createHash, randomUUID } from "node:crypto";
2
- import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
3
- import { homedir } from "node:os";
4
- import { dirname, join, resolve } from "node:path";
5
- import { resolveDuetAppBaseUrl } from "./duet-app-url.js";
6
- /**
7
- * Mirror of the chat-app default-skill sync, kept byte-identical so the
8
- * server's hash and the CLI's local hash match. The chat-app endpoint
9
- * already renders placeholders against the caller's org; the CLI just
10
- * verifies the returned hash and dumps the files into ~/.duet/skills/,
11
- * which the turn runner reads directly.
12
- *
13
- * The hash is used as a conditional GET ETag: we send the on-disk hash via
14
- * `If-None-Match` and the server returns `304 Not Modified` when it still
15
- * matches, so a no-op `duet login` never transfers the payload at all.
16
- */
17
- const DEFAULT_SKILLS_DIR = join(homedir(), ".duet", "skills");
18
- const DEFAULT_SKILLS_HASH_FILE = join(homedir(), ".duet", ".skills-hash");
19
- export async function fetchDefaultSkills(options) {
20
- const baseUrl = options.appBaseUrl ?? resolveDuetAppBaseUrl();
21
- const fetchFn = options.fetchFn ?? fetch;
22
- const headers = {
23
- Authorization: `Bearer ${options.apiKey}`,
24
- };
25
- if (options.knownHash) {
26
- headers["If-None-Match"] = `"${options.knownHash}"`;
27
- }
28
- const response = await fetchFn(`${baseUrl}/api/v1/cli/skills`, { headers });
29
- if (response.status === 304) {
30
- if (!options.knownHash) {
31
- throw new Error("Server returned 304 without a known hash to compare");
32
- }
33
- return { status: "not-modified", hash: options.knownHash };
34
- }
35
- if (!response.ok) {
36
- const detail = (await safeReadText(response)).slice(0, 256);
37
- throw new Error(`Failed to fetch default skills: ${response.status} ${response.statusText}${detail ? ` — ${detail}` : ""}`);
38
- }
39
- const etag = parseSkillHashEtag(response.headers.get("ETag"));
40
- if (!etag) {
41
- throw new Error("Skills response missing ETag header");
42
- }
43
- const body = (await response.json());
44
- if (!Array.isArray(body?.skills)) {
45
- throw new Error("Unexpected skills response shape");
46
- }
47
- const skills = body.skills;
48
- if (hashSkills(skills) !== etag) {
49
- throw new Error("Skill payload hash mismatch — refusing to write");
50
- }
51
- return { status: "modified", hash: etag, skills };
52
- }
53
- export function hashSkills(skills) {
54
- const hash = createHash("sha256");
55
- for (const skill of [...skills].sort((a, b) => a.path.localeCompare(b.path))) {
56
- hash.update(skill.path);
57
- hash.update("\0");
58
- hash.update(skill.content);
59
- hash.update("\0");
60
- }
61
- return hash.digest("hex");
62
- }
63
- function parseSkillHashEtag(etag) {
64
- if (!etag)
65
- return null;
66
- const match = etag.trim().match(/^(?:W\/)?"([^"]+)"$/);
67
- return match?.[1] ?? null;
68
- }
69
- /**
70
- * Best-effort startup sync. Skips silently when there is no API key, when
71
- * `~/.duet/.skills-hash` is absent (the user logged in without syncing), or
72
- * when the network call fails — startup must never block on a sync error.
73
- *
74
- * Returns the sync result on success, `null` when skipped, or `null` after a
75
- * caught error. Callers may inspect the return value to decide whether to
76
- * surface anything to the user.
77
- */
78
- export async function maybeAutoSyncDefaultSkills(options) {
79
- if (!options.apiKey)
80
- return null;
81
- const hashFilePath = options.hashFilePath ?? DEFAULT_SKILLS_HASH_FILE;
82
- if (!(await fileExists(hashFilePath)))
83
- return null;
84
- const log = options.logger ?? ((message) => process.stderr.write(`${message}\n`));
85
- try {
86
- return await syncDefaultSkills({ ...options, hashFilePath });
87
- }
88
- catch (err) {
89
- log(`Skill auto-sync failed: ${err instanceof Error ? err.message : String(err)}`);
90
- return null;
91
- }
92
- }
93
- async function fileExists(path) {
94
- try {
95
- return (await stat(path)).isFile();
96
- }
97
- catch {
98
- return false;
99
- }
100
- }
101
- export async function syncDefaultSkills(options) {
102
- const skillsDir = options.skillsDir ?? DEFAULT_SKILLS_DIR;
103
- const hashFilePath = options.hashFilePath ?? DEFAULT_SKILLS_HASH_FILE;
104
- const knownHash = await readExistingHash(hashFilePath);
105
- const fetched = await fetchDefaultSkills({
106
- apiKey: options.apiKey,
107
- appBaseUrl: options.appBaseUrl,
108
- fetchFn: options.fetchFn,
109
- knownHash,
110
- });
111
- if (fetched.status === "not-modified") {
112
- return { status: "unchanged", hash: fetched.hash };
113
- }
114
- // Stage the new tree in a sibling directory and swap it into place with a
115
- // single rename, rather than rewriting `skillsDir` in place. A second `duet`
116
- // process sharing this HOME can sync or read concurrently; an in-place
117
- // rebuild lets it observe a half-written tree, or rm the directory out from
118
- // under another sync's writes (`ENOENT ... open '.../<skill>'`). With staging
119
- // + rename an observer only ever sees the complete old tree or the new one.
120
- //
121
- // The token is unique per call, not per process: two syncs in the same
122
- // process and millisecond must not share scratch dirs or they stomp each
123
- // other's writes.
124
- const swapToken = randomUUID();
125
- const stagingDir = `${skillsDir}.staging-${swapToken}`;
126
- const retiredDir = `${skillsDir}.old-${swapToken}`;
127
- await rm(stagingDir, { recursive: true, force: true });
128
- await mkdir(stagingDir, { recursive: true });
129
- try {
130
- for (const skill of fetched.skills) {
131
- const target = resolve(stagingDir, skill.path);
132
- if (!isInsideDirectory(stagingDir, target)) {
133
- throw new Error(`Refusing to write skill outside ${skillsDir}: ${skill.path}`);
134
- }
135
- await mkdir(dirname(target), { recursive: true });
136
- await writeFile(target, skill.content);
137
- }
138
- await mkdir(dirname(skillsDir), { recursive: true });
139
- await swapIntoPlace(stagingDir, skillsDir, retiredDir);
140
- }
141
- finally {
142
- // Always clear scratch dirs: the retired tree on success, the staging tree
143
- // if we threw before the swap. force:true keeps this a no-op when absent.
144
- await rm(retiredDir, { recursive: true, force: true });
145
- await rm(stagingDir, { recursive: true, force: true });
146
- }
147
- await mkdir(dirname(hashFilePath), { recursive: true });
148
- await writeFile(hashFilePath, fetched.hash);
149
- return { status: "synced", hash: fetched.hash, count: fetched.skills.length };
150
- }
151
- /**
152
- * Replace `skillsDir` with the freshly built `stagingDir`. rename cannot
153
- * overwrite a non-empty directory, so the live tree is moved aside to
154
- * `retiredDir` first and then the staging tree is moved into place.
155
- *
156
- * Without a cross-process lock two concurrent syncs can race on the final
157
- * rename: the loser finds `skillsDir` already repopulated by the winner and
158
- * gets EEXIST/ENOTEMPTY. Since every default-skill sync fetches the same
159
- * payload, the winner's tree is a complete, correct result, so a lost race is
160
- * success, not failure — we retry the move-aside/swap a few times and then
161
- * accept a peer-installed tree rather than throwing. The destructive window is
162
- * a single rename, so a reader at worst momentarily sees `skillsDir` absent
163
- * (treated as "no skills") instead of a half-written tree.
164
- */
165
- async function swapIntoPlace(stagingDir, skillsDir, retiredDir) {
166
- const maxAttempts = 5;
167
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
168
- // Each attempt reuses retiredDir, so clear whatever a prior attempt parked
169
- // there before moving the live tree aside again.
170
- await rm(retiredDir, { recursive: true, force: true });
171
- try {
172
- await rename(skillsDir, retiredDir);
173
- }
174
- catch (err) {
175
- // ENOENT: no live tree to move aside (first sync, or a peer is mid-swap).
176
- if (err.code !== "ENOENT")
177
- throw err;
178
- }
179
- try {
180
- await rename(stagingDir, skillsDir);
181
- return;
182
- }
183
- catch (err) {
184
- const code = err.code;
185
- // A peer repopulated skillsDir between our move-aside and swap. Retry,
186
- // and on the final attempt accept their complete tree as the result.
187
- if (code !== "EEXIST" && code !== "ENOTEMPTY")
188
- throw err;
189
- if (attempt === maxAttempts - 1)
190
- return;
191
- }
192
- }
193
- }
194
- async function readExistingHash(path) {
195
- try {
196
- return (await readFile(path, "utf8")).trim() || null;
197
- }
198
- catch {
199
- return null;
200
- }
201
- }
202
- function isInsideDirectory(dir, candidate) {
203
- const resolved = resolve(candidate);
204
- const normalizedDir = resolve(dir) + (dir.endsWith("/") ? "" : "/");
205
- return resolved === resolve(dir) || resolved.startsWith(normalizedDir);
206
- }
207
- async function safeReadText(response) {
208
- try {
209
- return await response.text();
210
- }
211
- catch {
212
- return "";
213
- }
214
- }
215
- //# sourceMappingURL=sync-skills.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync-skills.js","sourceRoot":"","sources":["../../../src/lib/sync-skills.ts"],"names":[],"mappings":"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"}