@duetso/agent 0.1.34 → 0.1.35
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/package.json +1 -1
- package/dist/src/cli/env.d.ts +18 -0
- package/dist/src/cli/env.d.ts.map +1 -0
- package/dist/src/cli/env.js +114 -0
- package/dist/src/cli/env.js.map +1 -0
- package/dist/src/cli/help.d.ts +8 -0
- package/dist/src/cli/help.d.ts.map +1 -0
- package/dist/src/cli/help.js +175 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/login.d.ts +13 -0
- package/dist/src/cli/login.d.ts.map +1 -0
- package/dist/src/cli/login.js +61 -0
- package/dist/src/cli/login.js.map +1 -0
- package/dist/src/cli/memories-db.d.ts +24 -0
- package/dist/src/cli/memories-db.d.ts.map +1 -0
- package/dist/src/cli/memories-db.js +74 -0
- package/dist/src/cli/memories-db.js.map +1 -0
- package/dist/src/cli/memories-tui.d.ts +11 -0
- package/dist/src/cli/memories-tui.d.ts.map +1 -0
- package/dist/src/cli/memories-tui.js +266 -0
- package/dist/src/cli/memories-tui.js.map +1 -0
- package/dist/src/cli/memories.d.ts +9 -0
- package/dist/src/cli/memories.d.ts.map +1 -0
- package/dist/src/cli/memories.js +38 -0
- package/dist/src/cli/memories.js.map +1 -0
- package/dist/src/cli/package-manager.d.ts +38 -0
- package/dist/src/cli/package-manager.d.ts.map +1 -0
- package/dist/src/cli/package-manager.js +78 -0
- package/dist/src/cli/package-manager.js.map +1 -0
- package/dist/src/cli/resume-hint.d.ts +22 -0
- package/dist/src/cli/resume-hint.d.ts.map +1 -0
- package/dist/src/cli/resume-hint.js +61 -0
- package/dist/src/cli/resume-hint.js.map +1 -0
- package/dist/src/cli/run.d.ts +43 -0
- package/dist/src/cli/run.d.ts.map +1 -0
- package/dist/src/cli/run.js +273 -0
- package/dist/src/cli/run.js.map +1 -0
- package/dist/src/cli/shared.d.ts +55 -0
- package/dist/src/cli/shared.d.ts.map +1 -0
- package/dist/src/cli/shared.js +125 -0
- package/dist/src/cli/shared.js.map +1 -0
- package/dist/src/cli/skills.d.ts +10 -0
- package/dist/src/cli/skills.d.ts.map +1 -0
- package/dist/src/cli/skills.js +42 -0
- package/dist/src/cli/skills.js.map +1 -0
- package/dist/src/cli/upgrade.d.ts +9 -0
- package/dist/src/cli/upgrade.d.ts.map +1 -0
- package/dist/src/cli/upgrade.js +52 -0
- package/dist/src/cli/upgrade.js.map +1 -0
- package/dist/src/cli/version-check.d.ts +22 -0
- package/dist/src/cli/version-check.d.ts.map +1 -0
- package/dist/src/cli/version-check.js +78 -0
- package/dist/src/cli/version-check.js.map +1 -0
- package/dist/src/cli.d.ts +20 -63
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +38 -887
- package/dist/src/cli.js.map +1 -1
- package/dist/src/memory/observational-prompts.d.ts.map +1 -1
- package/dist/src/memory/observational-prompts.js +11 -7
- package/dist/src/memory/observational-prompts.js.map +1 -1
- package/dist/src/tui/app.d.ts +7 -47
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +204 -389
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/autocomplete.d.ts +91 -0
- package/dist/src/tui/autocomplete.d.ts.map +1 -0
- package/dist/src/tui/autocomplete.js +177 -0
- package/dist/src/tui/autocomplete.js.map +1 -0
- package/dist/src/tui/file-index.d.ts +11 -0
- package/dist/src/tui/file-index.d.ts.map +1 -0
- package/dist/src/tui/file-index.js +75 -0
- package/dist/src/tui/file-index.js.map +1 -0
- package/dist/src/tui/history.d.ts +50 -0
- package/dist/src/tui/history.d.ts.map +1 -0
- package/dist/src/tui/history.js +132 -0
- package/dist/src/tui/history.js.map +1 -0
- package/dist/src/tui/sidebar.d.ts +20 -0
- package/dist/src/tui/sidebar.d.ts.map +1 -0
- package/dist/src/tui/sidebar.js +118 -0
- package/dist/src/tui/sidebar.js.map +1 -0
- package/dist/src/tui/theme.d.ts +15 -0
- package/dist/src/tui/theme.d.ts.map +1 -0
- package/dist/src/tui/theme.js +18 -0
- package/dist/src/tui/theme.js.map +1 -0
- package/dist/src/turn-runner/prompts.d.ts.map +1 -1
- package/dist/src/turn-runner/prompts.js +7 -0
- package/dist/src/turn-runner/prompts.js.map +1 -1
- package/dist/src/turn-runner/tools.d.ts +15 -1
- package/dist/src/turn-runner/tools.d.ts.map +1 -1
- package/dist/src/turn-runner/tools.js +42 -9
- package/dist/src/turn-runner/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface EnvCommandIO {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
/** Override interactivity detection so tests can drive the paste flow. */
|
|
4
|
+
interactive?: boolean;
|
|
5
|
+
/** Inject a stand-in for the readline-backed key prompt. */
|
|
6
|
+
promptForApiKeys?: () => Promise<Map<string, string>>;
|
|
7
|
+
/** Inject a stand-in for the help-text printer. */
|
|
8
|
+
printHelp?: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run `duet env`.
|
|
12
|
+
*
|
|
13
|
+
* Two modes share a target env file: `--import` copies provider keys from a
|
|
14
|
+
* source env file (cwd .env by default), and `--keys` prompts the user for
|
|
15
|
+
* each supported provider key. Without either flag we just print help.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runEnvCommand(args: string[], io?: EnvCommandIO): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/cli/env.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DxF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { copyFile, mkdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
import { printEnvHelp } from "./help.js";
|
|
6
|
+
import { defaultDuetEnvFilePath, fail, fileExists, mergeEnvEntries, resolveUserPath, SUPPORTED_API_KEYS, } from "./shared.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run `duet env`.
|
|
9
|
+
*
|
|
10
|
+
* Two modes share a target env file: `--import` copies provider keys from a
|
|
11
|
+
* source env file (cwd .env by default), and `--keys` prompts the user for
|
|
12
|
+
* each supported provider key. Without either flag we just print help.
|
|
13
|
+
*/
|
|
14
|
+
export async function runEnvCommand(args, io = {}) {
|
|
15
|
+
const cwd = io.cwd ?? process.cwd();
|
|
16
|
+
let envFilePath;
|
|
17
|
+
let importEnvFilePath;
|
|
18
|
+
let pasteKeys = false;
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
switch (args[i]) {
|
|
21
|
+
case "--env-file":
|
|
22
|
+
if (!args[i + 1] || args[i + 1]?.startsWith("-"))
|
|
23
|
+
fail(`Missing value for ${args[i]}`);
|
|
24
|
+
envFilePath = args[++i];
|
|
25
|
+
break;
|
|
26
|
+
case "--import":
|
|
27
|
+
case "-i":
|
|
28
|
+
importEnvFilePath = args[i + 1]?.startsWith("-") ? "" : (args[++i] ?? "");
|
|
29
|
+
break;
|
|
30
|
+
case "--keys":
|
|
31
|
+
pasteKeys = true;
|
|
32
|
+
break;
|
|
33
|
+
case "--help":
|
|
34
|
+
case "-h":
|
|
35
|
+
printEnvHelp();
|
|
36
|
+
return;
|
|
37
|
+
default:
|
|
38
|
+
fail(`Unknown env option: ${args[i]}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const targetEnvFile = envFilePath ? resolveUserPath(envFilePath, cwd) : defaultDuetEnvFilePath();
|
|
42
|
+
const sourceEnvFile = importEnvFilePath === undefined
|
|
43
|
+
? undefined
|
|
44
|
+
: importEnvFilePath
|
|
45
|
+
? resolveUserPath(importEnvFilePath, cwd)
|
|
46
|
+
: join(cwd, ".env");
|
|
47
|
+
const interactive = io.interactive ?? Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
48
|
+
if (sourceEnvFile === undefined && !pasteKeys) {
|
|
49
|
+
(io.printHelp ?? printEnvHelp)();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (sourceEnvFile !== undefined) {
|
|
53
|
+
if (!(await fileExists(sourceEnvFile))) {
|
|
54
|
+
fail(`No .env file found at ${sourceEnvFile}`);
|
|
55
|
+
}
|
|
56
|
+
await importEnvFile(sourceEnvFile, targetEnvFile);
|
|
57
|
+
console.error(`Imported ${sourceEnvFile} into ${targetEnvFile}`);
|
|
58
|
+
}
|
|
59
|
+
if (pasteKeys) {
|
|
60
|
+
if (!interactive) {
|
|
61
|
+
fail("duet env --keys requires an interactive terminal");
|
|
62
|
+
}
|
|
63
|
+
const entries = await (io.promptForApiKeys ?? promptForApiKeys)();
|
|
64
|
+
if (entries.size === 0) {
|
|
65
|
+
console.error("No API keys entered.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await mergeEnvEntries(targetEnvFile, entries);
|
|
69
|
+
console.error(`Saved API keys to ${targetEnvFile}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Copy a source env file's contents into the target env file. When the
|
|
74
|
+
* target already exists we merge keys (source wins) instead of overwriting,
|
|
75
|
+
* so existing local settings stay intact.
|
|
76
|
+
*/
|
|
77
|
+
async function importEnvFile(source, target) {
|
|
78
|
+
if (resolve(source) === resolve(target)) {
|
|
79
|
+
console.error(`${target} is already the shared env file.`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
await mkdir(dirname(target), { recursive: true });
|
|
83
|
+
if (!(await fileExists(target))) {
|
|
84
|
+
await copyFile(source, target);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const parsed = dotenv.parse(await readFile(source));
|
|
88
|
+
await mergeEnvEntries(target, new Map(Object.entries(parsed)));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Prompt the user for each supported provider key on stderr; blank input
|
|
92
|
+
* skips that key. We use stderr so piping `duet env --keys` does not pollute
|
|
93
|
+
* stdout with prompt text.
|
|
94
|
+
*/
|
|
95
|
+
async function promptForApiKeys() {
|
|
96
|
+
const rl = createInterface({
|
|
97
|
+
input: process.stdin,
|
|
98
|
+
output: process.stderr,
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
const entries = new Map();
|
|
102
|
+
console.error("Paste API keys for any providers you want to use. Leave blank to skip.");
|
|
103
|
+
for (const key of SUPPORTED_API_KEYS) {
|
|
104
|
+
const value = (await rl.question(`${key}: `)).trim();
|
|
105
|
+
if (value)
|
|
106
|
+
entries.set(key, value);
|
|
107
|
+
}
|
|
108
|
+
return entries;
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
rl.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/cli/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const DEFAULT_RESUME_HISTORY_LINES = 40;
|
|
2
|
+
export declare function printRunHelp(packageName: string): void;
|
|
3
|
+
export declare function printLoginHelp(): void;
|
|
4
|
+
export declare function printEnvHelp(): void;
|
|
5
|
+
export declare function printSkillsHelp(): void;
|
|
6
|
+
export declare function printMemoriesHelp(): void;
|
|
7
|
+
export declare function printUpgradeHelp(packageName: string): void;
|
|
8
|
+
//# sourceMappingURL=help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAsEtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0BrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAkBtC;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAiBxC;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAa1D"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { DEFAULT_DUET_ENV_FILE, SUPPORTED_API_KEYS } from "./shared.js";
|
|
2
|
+
export const DEFAULT_RESUME_HISTORY_LINES = 40;
|
|
3
|
+
export function printRunHelp(packageName) {
|
|
4
|
+
console.log(`
|
|
5
|
+
duet — An opinionated full-stack agent runner
|
|
6
|
+
|
|
7
|
+
USAGE
|
|
8
|
+
duet [options] [prompt]
|
|
9
|
+
duet login [--no-browser] [--skip-skill-sync]
|
|
10
|
+
duet env [--env-file <path>] [--import [path]|--keys]
|
|
11
|
+
duet skills [--workdir <path>]
|
|
12
|
+
duet memories [--db <path>]
|
|
13
|
+
duet upgrade [--manager npm|bun|pnpm|yarn]
|
|
14
|
+
echo "prompt" | duet
|
|
15
|
+
|
|
16
|
+
COMMANDS
|
|
17
|
+
login Sign in via browser; saves DUET_API_KEY and syncs default skills (recommended)
|
|
18
|
+
env Manually create or update the shared duet env file with provider API keys
|
|
19
|
+
skills List installed skills as JSON (name, description, path, scope)
|
|
20
|
+
memories Open a TUI to view, edit, and delete observational memories
|
|
21
|
+
upgrade Upgrade the global ${packageName} installation
|
|
22
|
+
|
|
23
|
+
OPTIONS
|
|
24
|
+
-m, --model <name> TurnRunner model override
|
|
25
|
+
--memory-model <name> Observational memory model (default inferred from provider env)
|
|
26
|
+
--no-memory Keep memory in-process; do not read or write durable memory
|
|
27
|
+
-w, --workdir <path> Working directory (default: cwd)
|
|
28
|
+
-r, --resume <id> Resume a saved session
|
|
29
|
+
--resume-history-lines <n>
|
|
30
|
+
Display up to n prior-session lines in the TUI (default: ${DEFAULT_RESUME_HISTORY_LINES})
|
|
31
|
+
--system-prompt <text> Additional system instructions for the runner
|
|
32
|
+
--system-prompt-file <path>
|
|
33
|
+
Load a file into the system prompt; repeatable
|
|
34
|
+
--no-system-prompt-files Disable default AGENTS.md system prompt loading
|
|
35
|
+
--env-file <path> Shared env file to load after <workdir>/.env (default: ${DEFAULT_DUET_ENV_FILE})
|
|
36
|
+
--json Force JSONL event output instead of the TUI
|
|
37
|
+
-v, --version Print the installed duet version and exit
|
|
38
|
+
-h, --help Show this help
|
|
39
|
+
|
|
40
|
+
INTERACTIVE
|
|
41
|
+
In a TTY, duet keeps one local session open after terminal events.
|
|
42
|
+
Type /exit or /quit to end the conversation. Type @ followed by a
|
|
43
|
+
filename to insert a repo-relative path into the prompt.
|
|
44
|
+
|
|
45
|
+
MODELS
|
|
46
|
+
Prefer shorthands like opus-4.7, sonnet-4.6, haiku-4.5, and gpt-5.5.
|
|
47
|
+
They map to the first configured provider that supports that model.
|
|
48
|
+
Full provider:modelId syntax is also supported, e.g. anthropic:claude-opus-4-7.
|
|
49
|
+
If omitted, duet infers a default from ANTHROPIC_API_KEY,
|
|
50
|
+
DUET_API_KEY, AI_GATEWAY_API_KEY, OPENROUTER_API_KEY, or
|
|
51
|
+
OPENAI_API_KEY after loading <workdir>/.env and the shared duet env file.
|
|
52
|
+
|
|
53
|
+
duet-gateway: routes through the Duet gateway proxy
|
|
54
|
+
(https://duet.so/api/v1/ai-gateway by default; override the app origin
|
|
55
|
+
via DUET_APP_BASE_URL). It mirrors vercel-ai-gateway's model catalog
|
|
56
|
+
and authenticates with DUET_API_KEY.
|
|
57
|
+
|
|
58
|
+
EXAMPLES
|
|
59
|
+
duet "build a REST API with Express and TypeScript"
|
|
60
|
+
duet -m gpt-5.5 "analyze the performance of our test suite"
|
|
61
|
+
duet --memory-model sonnet-4.6 "summarize this repo"
|
|
62
|
+
duet -m opus-4.7 "refactor the auth module"
|
|
63
|
+
duet --system-prompt "Prefer concise answers." "review this repo"
|
|
64
|
+
duet --system-prompt-file TEAM.md "review this repo"
|
|
65
|
+
duet --env-file ~/.config/duet/env "review this repo"
|
|
66
|
+
duet --workdir ./my-project "refactor the auth module"
|
|
67
|
+
duet --resume session_abc123 --workdir ./my-project
|
|
68
|
+
duet login
|
|
69
|
+
duet env
|
|
70
|
+
duet memories
|
|
71
|
+
duet upgrade
|
|
72
|
+
`);
|
|
73
|
+
}
|
|
74
|
+
export function printLoginHelp() {
|
|
75
|
+
console.log(`
|
|
76
|
+
duet login — Sign in via browser and sync default skills
|
|
77
|
+
|
|
78
|
+
USAGE
|
|
79
|
+
duet login [--env-file <path>] [--no-browser] [--skip-skill-sync]
|
|
80
|
+
|
|
81
|
+
Opens a browser window pointed at the Duet web app, waits for the user to
|
|
82
|
+
confirm, then writes the org's DUET_API_KEY to the shared env file. After
|
|
83
|
+
auth, fetches and writes the latest default skills to ~/.duet/skills.
|
|
84
|
+
|
|
85
|
+
OPTIONS
|
|
86
|
+
--env-file <path> Env file to write the API key to (default: ${DEFAULT_DUET_ENV_FILE})
|
|
87
|
+
--no-browser Print the auth URL instead of opening a browser
|
|
88
|
+
--skip-skill-sync Skip the post-login default skills sync
|
|
89
|
+
-h, --help Show this help
|
|
90
|
+
|
|
91
|
+
SKILL SYNC
|
|
92
|
+
Mirrors the sandbox protocol: hashes the rendered skill payload and only
|
|
93
|
+
rewrites ~/.duet/skills when the hash differs from ~/.duet/.skills-hash.
|
|
94
|
+
|
|
95
|
+
OVERRIDES
|
|
96
|
+
Set DUET_APP_BASE_URL (e.g. https://staging.duet.so) to re-point both the
|
|
97
|
+
AI gateway provider and the CLI auth/sync endpoints at a non-production
|
|
98
|
+
deployment.
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
101
|
+
export function printEnvHelp() {
|
|
102
|
+
console.log(`
|
|
103
|
+
duet env — Create or update a shared duet env file
|
|
104
|
+
|
|
105
|
+
USAGE
|
|
106
|
+
duet env [--env-file <path>] [--import [path]|--keys]
|
|
107
|
+
|
|
108
|
+
Prefer \`duet login\` for the standard setup flow. Use \`duet env\` when you
|
|
109
|
+
want manual control over which provider API keys land in the shared env file.
|
|
110
|
+
|
|
111
|
+
By default, env only prints this help. Choose --import to copy
|
|
112
|
+
provider keys from cwd .env or a provided env file, or --keys to paste keys interactively.
|
|
113
|
+
|
|
114
|
+
OPTIONS
|
|
115
|
+
--env-file <path> Env file to write (default: ${DEFAULT_DUET_ENV_FILE})
|
|
116
|
+
-i, --import [path] Import cwd .env, or import the provided env file
|
|
117
|
+
--keys Prompt for supported provider API keys
|
|
118
|
+
-h, --help Show this help
|
|
119
|
+
|
|
120
|
+
SUPPORTED KEYS
|
|
121
|
+
${SUPPORTED_API_KEYS.join(", ")}
|
|
122
|
+
`);
|
|
123
|
+
}
|
|
124
|
+
export function printSkillsHelp() {
|
|
125
|
+
console.log(`
|
|
126
|
+
duet skills — List installed skills as JSON
|
|
127
|
+
|
|
128
|
+
USAGE
|
|
129
|
+
duet skills [--workdir <path>]
|
|
130
|
+
|
|
131
|
+
OPTIONS
|
|
132
|
+
-w, --workdir <path> Working directory for project-local skills (default: cwd)
|
|
133
|
+
-h, --help Show this help
|
|
134
|
+
|
|
135
|
+
OUTPUT
|
|
136
|
+
Prints a JSON array of installed skills. Each entry has:
|
|
137
|
+
name Skill name
|
|
138
|
+
description Skill description (from frontmatter, raw — no shell expansion)
|
|
139
|
+
path Absolute path to the skill directory
|
|
140
|
+
scope "user", "project", or "temporary"
|
|
141
|
+
`);
|
|
142
|
+
}
|
|
143
|
+
export function printMemoriesHelp() {
|
|
144
|
+
console.log(`
|
|
145
|
+
duet memories — Browse, edit, and delete observational memories
|
|
146
|
+
|
|
147
|
+
USAGE
|
|
148
|
+
duet memories [--db <path>]
|
|
149
|
+
|
|
150
|
+
OPTIONS
|
|
151
|
+
--db <path> Memory database path (default: ~/.duet/memory.db)
|
|
152
|
+
-h, --help Show this help
|
|
153
|
+
|
|
154
|
+
KEYS
|
|
155
|
+
↑ / ↓ Move selection
|
|
156
|
+
e Edit selected memory in $EDITOR
|
|
157
|
+
d Delete selected memory
|
|
158
|
+
q / Esc Quit
|
|
159
|
+
`);
|
|
160
|
+
}
|
|
161
|
+
export function printUpgradeHelp(packageName) {
|
|
162
|
+
console.log(`
|
|
163
|
+
duet upgrade — Upgrade the global ${packageName} installation
|
|
164
|
+
|
|
165
|
+
USAGE
|
|
166
|
+
duet upgrade [--manager npm|bun|pnpm|yarn] [--version <version>]
|
|
167
|
+
|
|
168
|
+
OPTIONS
|
|
169
|
+
--manager <name> Package manager to use (default: detected, fallback: npm)
|
|
170
|
+
--version <version> Install an exact version instead of npm's latest dist-tag
|
|
171
|
+
--dry-run Print the upgrade command without running it
|
|
172
|
+
-h, --help Show this help
|
|
173
|
+
`);
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAE/C,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;gDAiBkC,WAAW;;;;;;;;;uFAS4B,4BAA4B;;;;;oFAK/B,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCxG,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;wEAW0D,qBAAqB;;;;;;;;;;;;;CAa5F,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;yDAa2C,qBAAqB;;;;;;IAM1E,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;CAChC,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;CAgBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;CAeb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CAAC,GAAG,CAAC;oCACsB,WAAW;;;;;;;;;;CAU9C,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface LoginCommandIO {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
envFilePath?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Run `duet login`.
|
|
7
|
+
*
|
|
8
|
+
* Opens the duet web app in a browser, waits for confirmation, persists the
|
|
9
|
+
* returned `DUET_API_KEY` to the shared env file, then optionally syncs the
|
|
10
|
+
* org's default skills bundle to `~/.duet/skills`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runLoginCommand(args: string[], io?: LoginCommandIO): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/cli/login.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD5F"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { resolveDuetAppBaseUrl } from "../lib/duet-app-url.js";
|
|
2
|
+
import { loginWithBrowser } from "../lib/login.js";
|
|
3
|
+
import { syncDefaultSkills } from "../lib/sync-skills.js";
|
|
4
|
+
import { shimDuetApiKeyToAiGateway } from "../model-resolution/duet-gateway.js";
|
|
5
|
+
import { printLoginHelp } from "./help.js";
|
|
6
|
+
import { defaultDuetEnvFilePath, fail, mergeEnvEntries, resolveUserPath } from "./shared.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run `duet login`.
|
|
9
|
+
*
|
|
10
|
+
* Opens the duet web app in a browser, waits for confirmation, persists the
|
|
11
|
+
* returned `DUET_API_KEY` to the shared env file, then optionally syncs the
|
|
12
|
+
* org's default skills bundle to `~/.duet/skills`.
|
|
13
|
+
*/
|
|
14
|
+
export async function runLoginCommand(args, io = {}) {
|
|
15
|
+
const cwd = io.cwd ?? process.cwd();
|
|
16
|
+
let envFilePathOverride = io.envFilePath;
|
|
17
|
+
let noBrowser = false;
|
|
18
|
+
let skipSkillSync = false;
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
switch (args[i]) {
|
|
21
|
+
case "--env-file":
|
|
22
|
+
if (!args[i + 1] || args[i + 1]?.startsWith("-"))
|
|
23
|
+
fail(`Missing value for ${args[i]}`);
|
|
24
|
+
envFilePathOverride = args[++i];
|
|
25
|
+
break;
|
|
26
|
+
case "--no-browser":
|
|
27
|
+
noBrowser = true;
|
|
28
|
+
break;
|
|
29
|
+
case "--skip-skill-sync":
|
|
30
|
+
skipSkillSync = true;
|
|
31
|
+
break;
|
|
32
|
+
case "--help":
|
|
33
|
+
case "-h":
|
|
34
|
+
printLoginHelp();
|
|
35
|
+
return;
|
|
36
|
+
default:
|
|
37
|
+
fail(`Unknown login option: ${args[i]}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const targetEnvFile = envFilePathOverride
|
|
41
|
+
? resolveUserPath(envFilePathOverride, cwd)
|
|
42
|
+
: defaultDuetEnvFilePath();
|
|
43
|
+
const result = await loginWithBrowser({ noBrowser });
|
|
44
|
+
await mergeEnvEntries(targetEnvFile, new Map([["DUET_API_KEY", result.apiKey]]));
|
|
45
|
+
console.error(`Saved DUET_API_KEY for ${result.orgName} (${result.orgSlug}) to ${targetEnvFile}`);
|
|
46
|
+
process.env.DUET_API_KEY = result.apiKey;
|
|
47
|
+
shimDuetApiKeyToAiGateway();
|
|
48
|
+
if (skipSkillSync) {
|
|
49
|
+
console.error("Skipping default skill sync (--skip-skill-sync).");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.error(`Checking default skills against ${resolveDuetAppBaseUrl()}...`);
|
|
53
|
+
const syncResult = await syncDefaultSkills({ apiKey: result.apiKey });
|
|
54
|
+
if (syncResult.status === "unchanged") {
|
|
55
|
+
console.error("Default skills already up to date.");
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.error(`Synced ${syncResult.count} default skills.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Observation } from "../types/memory.js";
|
|
2
|
+
/**
|
|
3
|
+
* Thin read/edit/delete wrapper over the PGlite database `MemoryStore` writes
|
|
4
|
+
* to. The `duet memories` command opens the same on-disk file, so changes
|
|
5
|
+
* made here are visible to subsequent runner sessions.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MemoryDb {
|
|
8
|
+
private readonly db;
|
|
9
|
+
private constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Open the memory database at `path`, creating the file and parent
|
|
12
|
+
* directory if needed. The schema matches `memory/storage.ts` so the
|
|
13
|
+
* runner and this CLI command share one source of truth.
|
|
14
|
+
*/
|
|
15
|
+
static open(path: string): Promise<MemoryDb>;
|
|
16
|
+
/** Load all observations ordered most recent first. */
|
|
17
|
+
list(): Promise<Observation[]>;
|
|
18
|
+
/** Replace just the `content` of an observation, preserving everything else. */
|
|
19
|
+
updateContent(id: string, content: string): Promise<void>;
|
|
20
|
+
/** Permanently remove an observation. There is no undo. */
|
|
21
|
+
delete(id: string): Promise<void>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=memories-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memories-db.d.ts","sourceRoot":"","sources":["../../../src/cli/memories-db.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,QAAQ;IACC,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAvC,OAAO;IAEP;;;;OAIG;WACU,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAqBlD,uDAAuD;IACjD,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAUpC,gFAAgF;IAC1E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,2DAA2D;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
/**
|
|
5
|
+
* Thin read/edit/delete wrapper over the PGlite database `MemoryStore` writes
|
|
6
|
+
* to. The `duet memories` command opens the same on-disk file, so changes
|
|
7
|
+
* made here are visible to subsequent runner sessions.
|
|
8
|
+
*/
|
|
9
|
+
export class MemoryDb {
|
|
10
|
+
db;
|
|
11
|
+
constructor(db) {
|
|
12
|
+
this.db = db;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Open the memory database at `path`, creating the file and parent
|
|
16
|
+
* directory if needed. The schema matches `memory/storage.ts` so the
|
|
17
|
+
* runner and this CLI command share one source of truth.
|
|
18
|
+
*/
|
|
19
|
+
static async open(path) {
|
|
20
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
21
|
+
const db = new PGlite(path);
|
|
22
|
+
await db.exec(`
|
|
23
|
+
CREATE TABLE IF NOT EXISTS observations (
|
|
24
|
+
id TEXT PRIMARY KEY,
|
|
25
|
+
created_at BIGINT NOT NULL,
|
|
26
|
+
observed_date TEXT NOT NULL,
|
|
27
|
+
referenced_date TEXT,
|
|
28
|
+
relative_date TEXT,
|
|
29
|
+
time_of_day TEXT,
|
|
30
|
+
priority TEXT NOT NULL,
|
|
31
|
+
scope TEXT NOT NULL,
|
|
32
|
+
source_json TEXT NOT NULL,
|
|
33
|
+
content TEXT NOT NULL,
|
|
34
|
+
tags_json TEXT NOT NULL
|
|
35
|
+
);
|
|
36
|
+
`);
|
|
37
|
+
return new MemoryDb(db);
|
|
38
|
+
}
|
|
39
|
+
/** Load all observations ordered most recent first. */
|
|
40
|
+
async list() {
|
|
41
|
+
const result = await this.db.query(`SELECT id, created_at, observed_date, referenced_date, relative_date, time_of_day,
|
|
42
|
+
priority, scope, source_json, content, tags_json
|
|
43
|
+
FROM observations
|
|
44
|
+
ORDER BY created_at DESC`);
|
|
45
|
+
return result.rows.map(rowToObservation);
|
|
46
|
+
}
|
|
47
|
+
/** Replace just the `content` of an observation, preserving everything else. */
|
|
48
|
+
async updateContent(id, content) {
|
|
49
|
+
await this.db.query(`UPDATE observations SET content = $1 WHERE id = $2`, [content, id]);
|
|
50
|
+
}
|
|
51
|
+
/** Permanently remove an observation. There is no undo. */
|
|
52
|
+
async delete(id) {
|
|
53
|
+
await this.db.query(`DELETE FROM observations WHERE id = $1`, [id]);
|
|
54
|
+
}
|
|
55
|
+
async close() {
|
|
56
|
+
await this.db.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function rowToObservation(row) {
|
|
60
|
+
return {
|
|
61
|
+
id: row.id,
|
|
62
|
+
createdAt: row.created_at,
|
|
63
|
+
observedDate: row.observed_date,
|
|
64
|
+
...(row.referenced_date !== null ? { referencedDate: row.referenced_date } : {}),
|
|
65
|
+
...(row.relative_date !== null ? { relativeDate: row.relative_date } : {}),
|
|
66
|
+
...(row.time_of_day !== null ? { timeOfDay: row.time_of_day } : {}),
|
|
67
|
+
priority: row.priority,
|
|
68
|
+
scope: row.scope,
|
|
69
|
+
source: JSON.parse(row.source_json),
|
|
70
|
+
content: row.content,
|
|
71
|
+
tags: JSON.parse(row.tags_json),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=memories-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memories-db.js","sourceRoot":"","sources":["../../../src/cli/memories-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;;;GAIG;AACH,MAAM,OAAO,QAAQ;IACkB;IAArC,YAAqC,EAAU;QAAV,OAAE,GAAF,EAAE,CAAQ;IAAG,CAAC;IAEnD;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAY;QAC5B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;KAcb,CAAC,CAAC;QACH,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,IAAI;QACR,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAChC;;;gCAG0B,CAC3B,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,aAAa,CAAC,EAAU,EAAE,OAAe;QAC7C,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,oDAAoD,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,wCAAwC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF;AAgBD,SAAS,gBAAgB,CAAC,GAAmB;IAC3C,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,GAAG,CAAC,GAAG,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,GAAG,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAA0B;QAC5D,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAa;KAC5C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MemoryDb } from "./memories-db.js";
|
|
2
|
+
/**
|
|
3
|
+
* Run the interactive memories browser.
|
|
4
|
+
*
|
|
5
|
+
* Renders observations in a scrollable list with metadata per row, lets the
|
|
6
|
+
* user navigate with the arrow keys, edit the selected memory's content via
|
|
7
|
+
* `$EDITOR` (or vi as a fallback), or delete it outright. All edits and
|
|
8
|
+
* deletes hit `db` directly so the runner sees them on its next session.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runMemoriesTui(db: MemoryDb, dbPath: string): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=memories-tui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memories-tui.d.ts","sourceRoot":"","sources":["../../../src/cli/memories-tui.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6MhF"}
|