@duetso/agent 0.1.70 → 0.1.72

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 (37) hide show
  1. package/dist/package.json +1 -1
  2. package/dist/src/cli/help.d.ts +1 -0
  3. package/dist/src/cli/help.d.ts.map +1 -1
  4. package/dist/src/cli/help.js +21 -0
  5. package/dist/src/cli/help.js.map +1 -1
  6. package/dist/src/cli/send-feedback.d.ts +23 -0
  7. package/dist/src/cli/send-feedback.d.ts.map +1 -0
  8. package/dist/src/cli/send-feedback.js +95 -0
  9. package/dist/src/cli/send-feedback.js.map +1 -0
  10. package/dist/src/cli.d.ts +2 -0
  11. package/dist/src/cli.d.ts.map +1 -1
  12. package/dist/src/cli.js +6 -0
  13. package/dist/src/cli.js.map +1 -1
  14. package/dist/src/lib/feedback.d.ts +27 -0
  15. package/dist/src/lib/feedback.d.ts.map +1 -0
  16. package/dist/src/lib/feedback.js +37 -0
  17. package/dist/src/lib/feedback.js.map +1 -0
  18. package/dist/src/tui/app.d.ts.map +1 -1
  19. package/dist/src/tui/app.js +74 -4
  20. package/dist/src/tui/app.js.map +1 -1
  21. package/dist/src/tui/autocomplete.d.ts.map +1 -1
  22. package/dist/src/tui/autocomplete.js +5 -0
  23. package/dist/src/tui/autocomplete.js.map +1 -1
  24. package/dist/src/tui/sidebar.d.ts.map +1 -1
  25. package/dist/src/tui/sidebar.js +63 -59
  26. package/dist/src/tui/sidebar.js.map +1 -1
  27. package/dist/src/tui/theme.d.ts +1 -1
  28. package/dist/src/tui/theme.d.ts.map +1 -1
  29. package/dist/src/tui/theme.js +5 -1
  30. package/dist/src/tui/theme.js.map +1 -1
  31. package/dist/src/turn-runner/turn-runner.d.ts +25 -9
  32. package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
  33. package/dist/src/turn-runner/turn-runner.js +90 -13
  34. package/dist/src/turn-runner/turn-runner.js.map +1 -1
  35. package/dist/src/types/protocol.d.ts +3 -0
  36. package/dist/src/types/protocol.d.ts.map +1 -1
  37. package/package.json +1 -1
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duetso/agent",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "description": "An opinionated full-stack agent turn runner with native memories, interrupts, and multi-agent orchestration",
5
5
  "keywords": [
6
6
  "agent",
@@ -10,5 +10,6 @@ export declare function printLoginHelp(): void;
10
10
  export declare function printEnvHelp(): void;
11
11
  export declare function printSkillsHelp(): void;
12
12
  export declare function printMemoryHelp(): void;
13
+ export declare function printSendFeedbackHelp(): void;
13
14
  export declare function printUpgradeHelp(packageName: string): void;
14
15
  //# sourceMappingURL=help.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CA+EtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0BrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAkBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAoBtC;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAa1D"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/help.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAkFtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CA0BrC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAsBnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAkBtC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAoBtC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAiB5C;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAa1D"}
@@ -16,6 +16,7 @@ USAGE
16
16
  duet env [--env-file <path>] [--import [path]|--keys]
17
17
  duet skills [--workdir <path>]
18
18
  duet memory [--db <path>]
19
+ duet send-feedback [--file <path>] [text...]
19
20
  duet upgrade [--manager npm|bun|pnpm|yarn]
20
21
  echo "prompt" | duet
21
22
 
@@ -24,6 +25,7 @@ COMMANDS
24
25
  env Manually create or update the shared duet env file with provider API keys
25
26
  skills List installed skills as JSON (name, description, path, scope)
26
27
  memory Open a TUI to view, edit, and delete observational memories (alias: memories)
28
+ send-feedback Send free-form markdown feedback to the Duet team
27
29
  upgrade Upgrade the global ${packageName} installation
28
30
 
29
31
  OPTIONS
@@ -83,6 +85,7 @@ EXAMPLES
83
85
  duet login
84
86
  duet env
85
87
  duet memory
88
+ duet send-feedback "the TUI flickers when..."
86
89
  duet upgrade
87
90
  `);
88
91
  }
@@ -176,6 +179,24 @@ KEYS
176
179
  q / Esc Quit
177
180
  `);
178
181
  }
182
+ export function printSendFeedbackHelp() {
183
+ console.log(`
184
+ duet send-feedback — Send free-form markdown feedback to the Duet team
185
+
186
+ USAGE
187
+ duet send-feedback [text...]
188
+ duet send-feedback --file <path>
189
+ echo "feedback" | duet send-feedback
190
+
191
+ Submits a piece of markdown feedback to the Duet team's triage queue. The
192
+ endpoint is public — no API key required. With no input, drops you into an
193
+ interactive prompt; submit an empty line to send.
194
+
195
+ OPTIONS
196
+ -f, --file <path> Read feedback content from a file
197
+ -h, --help Show this help
198
+ `);
199
+ }
179
200
  export function printUpgradeHelp(packageName) {
180
201
  console.log(`
181
202
  duet upgrade — Upgrade the global ${packageName} installation
@@ -1 +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;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;gDAiBkC,WAAW;;;;;;;;;;;;gHAYqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CxG,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,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;CAkBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CAAC,GAAG,CAAC;oCACsB,WAAW;;;;;;;;;;CAU9C,CAAC,CAAC;AACH,CAAC"}
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;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;gDAmBkC,WAAW;;;;;;;;;;;;gHAYqD,+BAA+B;;;;;oFAK3D,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CxG,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,eAAe;IAC7B,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;CAkBb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,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,23 @@
1
+ export interface SendFeedbackCommandIO {
2
+ cwd?: string;
3
+ /** Inject a stand-in for the readline-backed prompt so tests can drive it. */
4
+ promptForFeedback?: () => Promise<string>;
5
+ /** Inject a stand-in for fetch so tests can intercept the upload. */
6
+ fetch?: typeof fetch;
7
+ }
8
+ /**
9
+ * Run `duet send-feedback`.
10
+ *
11
+ * Submits a piece of free-form markdown feedback to the chat-app's public
12
+ * feedback endpoint. No API key required — the endpoint is intentionally
13
+ * unauthenticated so external clients can drop notes into the team's triage
14
+ * queue without a login.
15
+ *
16
+ * Content sources, in priority order:
17
+ * 1. Positional argument (e.g. `duet send-feedback "thing is broken"`)
18
+ * 2. `--file <path>` (read markdown from a file)
19
+ * 3. stdin if piped
20
+ * 4. Interactive prompt
21
+ */
22
+ export declare function runSendFeedbackCommand(args: string[], io?: SendFeedbackCommandIO): Promise<void>;
23
+ //# sourceMappingURL=send-feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-feedback.d.ts","sourceRoot":"","sources":["../../../src/cli/send-feedback.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,qBAA0B,GAC7B,OAAO,CAAC,IAAI,CAAC,CAmDf"}
@@ -0,0 +1,95 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { createInterface } from "node:readline/promises";
3
+ import { submitDuetFeedback } from "../lib/feedback.js";
4
+ import { printSendFeedbackHelp } from "./help.js";
5
+ import { fail, isInteractive, resolveUserPath } from "./shared.js";
6
+ /**
7
+ * Run `duet send-feedback`.
8
+ *
9
+ * Submits a piece of free-form markdown feedback to the chat-app's public
10
+ * feedback endpoint. No API key required — the endpoint is intentionally
11
+ * unauthenticated so external clients can drop notes into the team's triage
12
+ * queue without a login.
13
+ *
14
+ * Content sources, in priority order:
15
+ * 1. Positional argument (e.g. `duet send-feedback "thing is broken"`)
16
+ * 2. `--file <path>` (read markdown from a file)
17
+ * 3. stdin if piped
18
+ * 4. Interactive prompt
19
+ */
20
+ export async function runSendFeedbackCommand(args, io = {}) {
21
+ const cwd = io.cwd ?? process.cwd();
22
+ let filePath;
23
+ const positional = [];
24
+ for (let i = 0; i < args.length; i++) {
25
+ switch (args[i]) {
26
+ case "--file":
27
+ case "-f":
28
+ if (!args[i + 1] || args[i + 1]?.startsWith("-"))
29
+ fail(`Missing value for ${args[i]}`);
30
+ filePath = args[++i];
31
+ break;
32
+ case "--help":
33
+ case "-h":
34
+ printSendFeedbackHelp();
35
+ return;
36
+ default: {
37
+ const arg = args[i];
38
+ if (arg.startsWith("-"))
39
+ fail(`Unknown send-feedback option: ${arg}`);
40
+ positional.push(arg);
41
+ }
42
+ }
43
+ }
44
+ let content = positional.join(" ").trim();
45
+ if (!content && filePath) {
46
+ content = (await readFile(resolveUserPath(filePath, cwd), "utf8")).trim();
47
+ }
48
+ if (!content && !process.stdin.isTTY) {
49
+ content = (await readStdin()).trim();
50
+ }
51
+ if (!content) {
52
+ if (!isInteractive()) {
53
+ fail("No feedback provided. Pass it as an argument, via --file, or pipe it on stdin.");
54
+ }
55
+ content = (await (io.promptForFeedback ?? promptForFeedback)()).trim();
56
+ }
57
+ if (!content) {
58
+ fail("Feedback content is required.");
59
+ }
60
+ try {
61
+ const { baseUrl } = await submitDuetFeedback({ content, fetch: io.fetch });
62
+ console.error(`Thanks! Feedback sent to ${baseUrl}.`);
63
+ }
64
+ catch (error) {
65
+ fail(error instanceof Error ? error.message : String(error));
66
+ }
67
+ }
68
+ async function readStdin() {
69
+ const chunks = [];
70
+ for await (const chunk of process.stdin) {
71
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
72
+ }
73
+ return Buffer.concat(chunks).toString("utf8");
74
+ }
75
+ async function promptForFeedback() {
76
+ const rl = createInterface({
77
+ input: process.stdin,
78
+ output: process.stderr,
79
+ });
80
+ try {
81
+ console.error("Type your feedback (markdown). Submit an empty line to send.");
82
+ const lines = [];
83
+ while (true) {
84
+ const line = await rl.question("> ");
85
+ if (line.length === 0)
86
+ break;
87
+ lines.push(line);
88
+ }
89
+ return lines.join("\n");
90
+ }
91
+ finally {
92
+ rl.close();
93
+ }
94
+ }
95
+ //# sourceMappingURL=send-feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-feedback.js","sourceRoot":"","sources":["../../../src/cli/send-feedback.ts"],"names":[],"mappings":"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"}
package/dist/src/cli.d.ts CHANGED
@@ -21,6 +21,8 @@ export type { LoginCommandIO } from "./cli/login.js";
21
21
  export { runSkillsCommand } from "./cli/skills.js";
22
22
  export { runUpgradeCommand } from "./cli/upgrade.js";
23
23
  export { runMemoryCommand } from "./cli/memory.js";
24
+ export { runSendFeedbackCommand } from "./cli/send-feedback.js";
25
+ export type { SendFeedbackCommandIO } from "./cli/send-feedback.js";
24
26
  export { cliEnvFilePaths, defaultDuetEnvFilePath, fileExists, formatEnvEntries, loadCliEnvFiles, parseResumeHistoryMessages, resolveUserPath, shellQuote, } from "./cli/shared.js";
25
27
  export { detectPackageManagerFromContext, globalUpgradeCommand } from "./cli/package-manager.js";
26
28
  export type { PackageManager, PackageManagerDetectionContext } from "./cli/package-manager.js";
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG;AAiBH,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,0BAA0B,EAC1B,eAAe,EACf,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,+BAA+B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACjG,YAAY,EAAE,cAAc,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG;AAkBH,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,0BAA0B,EAC1B,eAAe,EACf,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,+BAA+B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACjG,YAAY,EAAE,cAAc,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/src/cli.js CHANGED
@@ -18,6 +18,7 @@ import { runLoginCommand } from "./cli/login.js";
18
18
  import { runMemoryCommand } from "./cli/memory.js";
19
19
  import { runRpcCommand } from "./cli/rpc.js";
20
20
  import { runRunCommand } from "./cli/run.js";
21
+ import { runSendFeedbackCommand } from "./cli/send-feedback.js";
21
22
  import { runSkillsCommand } from "./cli/skills.js";
22
23
  import { runUpgradeCommand } from "./cli/upgrade.js";
23
24
  import { shimDuetApiKeyToAiGateway } from "./model-resolution/duet-gateway.js";
@@ -28,6 +29,7 @@ export { runLoginCommand } from "./cli/login.js";
28
29
  export { runSkillsCommand } from "./cli/skills.js";
29
30
  export { runUpgradeCommand } from "./cli/upgrade.js";
30
31
  export { runMemoryCommand } from "./cli/memory.js";
32
+ export { runSendFeedbackCommand } from "./cli/send-feedback.js";
31
33
  export { cliEnvFilePaths, defaultDuetEnvFilePath, fileExists, formatEnvEntries, loadCliEnvFiles, parseResumeHistoryMessages, resolveUserPath, shellQuote, } from "./cli/shared.js";
32
34
  export { detectPackageManagerFromContext, globalUpgradeCommand } from "./cli/package-manager.js";
33
35
  export { compareSemverVersions, fetchLatestPackageVersion } from "./cli/version-check.js";
@@ -64,6 +66,10 @@ async function main() {
64
66
  await runMemoryCommand(args.slice(1));
65
67
  return;
66
68
  }
69
+ if (subcommand === "send-feedback") {
70
+ await runSendFeedbackCommand(args.slice(1));
71
+ return;
72
+ }
67
73
  // `--rpc` is a top-level routing flag rather than a subcommand because it
68
74
  // shares all model/workdir/env flags with the default run command; the
69
75
  // difference is only the I/O surface (stdin commands, stdout events).
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Source identifier stamped on every CLI/TUI feedback row so the admin
3
+ * inbox can distinguish them from the in-product web sidebar dialog.
4
+ */
5
+ export declare const DUET_AGENT_FEEDBACK_SOURCE = "duet-agent-cli";
6
+ export interface SubmitFeedbackOptions {
7
+ content: string;
8
+ /** Override the source string used by web admin filters. */
9
+ source?: string;
10
+ /** Inject a stand-in for fetch so tests can intercept the upload. */
11
+ fetch?: typeof fetch;
12
+ }
13
+ export interface SubmitFeedbackResult {
14
+ /** Base URL the feedback was POSTed to, for confirmation messages. */
15
+ baseUrl: string;
16
+ }
17
+ /**
18
+ * POST a free-form markdown feedback string to the Duet web app's public
19
+ * feedback endpoint. Shared between `duet send-feedback` (CLI) and the
20
+ * `/feedback` TUI slash command. The endpoint is intentionally
21
+ * unauthenticated — anonymous notes are fine.
22
+ *
23
+ * Throws on non-2xx responses so callers can surface the error in their
24
+ * own UI surface (stderr for the CLI, an error block for the TUI).
25
+ */
26
+ export declare function submitDuetFeedback(options: SubmitFeedbackOptions): Promise<SubmitFeedbackResult>;
27
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../src/lib/feedback.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,0BAA0B,mBAAmB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAwB/B"}
@@ -0,0 +1,37 @@
1
+ import { resolveDuetAppBaseUrl } from "./duet-app-url.js";
2
+ /**
3
+ * Source identifier stamped on every CLI/TUI feedback row so the admin
4
+ * inbox can distinguish them from the in-product web sidebar dialog.
5
+ */
6
+ export const DUET_AGENT_FEEDBACK_SOURCE = "duet-agent-cli";
7
+ /**
8
+ * POST a free-form markdown feedback string to the Duet web app's public
9
+ * feedback endpoint. Shared between `duet send-feedback` (CLI) and the
10
+ * `/feedback` TUI slash command. The endpoint is intentionally
11
+ * unauthenticated — anonymous notes are fine.
12
+ *
13
+ * Throws on non-2xx responses so callers can surface the error in their
14
+ * own UI surface (stderr for the CLI, an error block for the TUI).
15
+ */
16
+ export async function submitDuetFeedback(options) {
17
+ const trimmed = options.content.trim();
18
+ if (!trimmed)
19
+ throw new Error("Feedback content is required.");
20
+ const baseUrl = resolveDuetAppBaseUrl();
21
+ const url = `${baseUrl}/api/v1/feedback`;
22
+ const fetchImpl = options.fetch ?? globalThis.fetch;
23
+ const response = await fetchImpl(url, {
24
+ method: "POST",
25
+ headers: { "Content-Type": "application/json" },
26
+ body: JSON.stringify({
27
+ content: trimmed,
28
+ source: options.source ?? DUET_AGENT_FEEDBACK_SOURCE,
29
+ }),
30
+ });
31
+ if (!response.ok) {
32
+ const text = await response.text().catch(() => "");
33
+ throw new Error(`Feedback submission failed (${response.status}): ${text || response.statusText}`);
34
+ }
35
+ return { baseUrl };
36
+ }
37
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../../src/lib/feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CAAC;AAe3D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAA8B;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAE/D,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,GAAG,OAAO,kBAAkB,CAAC;IACzC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACpD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QACpC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,0BAA0B;SACrD,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,+BAA+B,QAAQ,CAAC,MAAM,MAAM,IAAI,IAAI,QAAQ,CAAC,UAAU,EAAE,CAClF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/tui/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAEL,KAAK,WAAW,EAWjB,MAAM,eAAe,CAAC;AAavB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAMV,iBAAiB,EAElB,MAAM,sBAAsB,CAAC;AAmC9B,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1F,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EACV,iBAAiB,EACjB,iBAAiB,IAAI,sBAAsB,EAC3C,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,uBAAuB,EACvB,+BAA+B,EAC/B,kCAAkC,EAClC,qBAAqB,EACrB,8BAA8B,EAC9B,YAAY,EACZ,oBAAoB,EACpB,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAUD;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAs0EvF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/tui/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAEL,KAAK,WAAW,EAWjB,MAAM,eAAe,CAAC;AAavB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAMV,iBAAiB,EAElB,MAAM,sBAAsB,CAAC;AAmC9B,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1F,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EACV,iBAAiB,EACjB,iBAAiB,IAAI,sBAAsB,EAC3C,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,EAClB,uBAAuB,EACvB,+BAA+B,EAC/B,kCAAkC,EAClC,qBAAqB,EACrB,8BAA8B,EAC9B,YAAY,EACZ,oBAAoB,EACpB,4BAA4B,EAC5B,6BAA6B,EAC7B,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAUD;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAm5EvF"}
@@ -5,6 +5,7 @@ import { parseCopyArgument, selectCopyText } from "./transcript-log.js";
5
5
  import { describeUpgradeStatus, } from "../cli/auto-upgrade.js";
6
6
  import { activeFileAutocompleteToken, activeSkillAutocompleteToken, AUTOCOMPLETE_LIMITS, BUILT_IN_SLASH_COMMANDS, commitActiveAnswer, fileAutocompleteMatches, formatQuestionOptionDescription, formatSkillAutocompleteDescription, moveQuestionHighlight, moveSkillAutocompleteSelection, NO_HIGHLIGHT, restoreSavedAnswer, skillAutocompleteMatches, } from "./autocomplete.js";
7
7
  import { homedir } from "node:os";
8
+ import { submitDuetFeedback } from "../lib/feedback.js";
8
9
  import { buildFileIndex } from "./file-index.js";
9
10
  import { DUET_BANNER_LINES_COMPACT, historyDisplayBlocks, limitHistoryDisplayMessages, } from "./history.js";
10
11
  import { listRecentSessions } from "./recent-sessions.js";
@@ -1599,15 +1600,31 @@ export async function runTui(input) {
1599
1600
  }
1600
1601
  }
1601
1602
  if (key.name === "return" || key.name === "enter") {
1602
- // Shift+Enter inserts a literal newline at the cursor, matching every
1603
- // modern chat composer (Slack, Claude Code, ChatGPT, Discord). Plain
1604
- // Enter always submits when the agent is running the submit path
1605
- // queues the message as a follow-up; otherwise it kicks off a new turn.
1603
+ // Three modifier flavors on the Enter key. The modifier is only
1604
+ // distinguishable when the terminal speaks the kitty-keyboard
1605
+ // protocol (or modifyOtherKeys); in a legacy terminal Ctrl+Enter
1606
+ // and Shift+Enter collapse to plain Enter. We accept that
1607
+ // tradeoff for the same reason Shift+Enter accepts it: modern
1608
+ // terminals are the target.
1609
+ //
1610
+ // Plain Enter → submit (idle = fresh turn, running = soft queue
1611
+ // via follow_up).
1612
+ // Shift+Enter → insert a literal newline at the cursor, matching
1613
+ // every modern chat composer (Slack, ChatGPT,
1614
+ // Discord, Cursor, Claude Code).
1615
+ // Ctrl+Enter → steer: dispatch with behavior:"steer" so the
1616
+ // runner hands it to agent.steer() at the next
1617
+ // inference boundary instead of waiting for the
1618
+ // full turn to wrap up.
1606
1619
  key.preventDefault();
1607
1620
  if (key.shift) {
1608
1621
  inputField.insertText("\n");
1609
1622
  return;
1610
1623
  }
1624
+ if (key.ctrl) {
1625
+ handleSteerKeystroke();
1626
+ return;
1627
+ }
1611
1628
  const value = inputField.plainText.trim();
1612
1629
  inputField.clear();
1613
1630
  if (value) {
@@ -1636,6 +1653,40 @@ export async function runTui(input) {
1636
1653
  return;
1637
1654
  void input.session.interrupt().catch(reportError);
1638
1655
  }
1656
+ // Ctrl+Enter sends the composer text with behavior:"steer" — the
1657
+ // runner routes this to agent.steer() when the agent is mid-inference
1658
+ // (most of an active turn), which preempts the current LLM call and
1659
+ // injects the message into the next iteration. If the runner is
1660
+ // between inference calls (e.g. mid-tool-call) the steer-flagged
1661
+ // command enqueues and gets picked up at the next agent boundary.
1662
+ // Either way the user gets "at next sensible task boundary" pickup,
1663
+ // which is sooner than the soft-queue follow_up (which only fires at
1664
+ // end of the full turn).
1665
+ //
1666
+ // Empty composer: no-op. The keybind is dedicated to send-with-steer,
1667
+ // and a bare Ctrl+Enter should not interrupt or otherwise affect state.
1668
+ function handleSteerKeystroke() {
1669
+ const message = inputField.plainText.trim();
1670
+ if (message.length === 0)
1671
+ return;
1672
+ // Snapshot before clearing so attachments ride with the steer
1673
+ // dispatch and the user-facing labels render correctly.
1674
+ const submittedImages = pendingImages;
1675
+ inputField.clear();
1676
+ clearPendingImages();
1677
+ refreshHint();
1678
+ recordTranscriptEntry("user", message);
1679
+ appendBlock("you:", message, COLORS.user);
1680
+ if (submittedImages.length > 0) {
1681
+ const lines = submittedImages.map((p) => `📎 ${p.label}: ${p.path}`).join("\n");
1682
+ appendBlock(null, lines, COLORS.hint);
1683
+ }
1684
+ const images = submittedImages.map((p) => p.attachment);
1685
+ void input.session.prompt({ message, behavior: "steer", images }).catch(reportError);
1686
+ if (!running) {
1687
+ markRunning();
1688
+ }
1689
+ }
1639
1690
  // ---- /diag diagnostics -----------------------------------------------------
1640
1691
  // `/diag` toggles a key+selection event log so the user can show us
1641
1692
  // exactly what their terminal forwards when something silently fails
@@ -1885,6 +1936,10 @@ export async function runTui(input) {
1885
1936
  handleDiagSlashCommand(message);
1886
1937
  return;
1887
1938
  }
1939
+ if (message === "/feedback" || message.startsWith("/feedback ")) {
1940
+ void handleFeedbackSlashCommand(message);
1941
+ return;
1942
+ }
1888
1943
  const submittedImages = pendingImages;
1889
1944
  recordTranscriptEntry("user", message);
1890
1945
  appendBlock("you:", message, COLORS.user);
@@ -2031,6 +2086,21 @@ export async function runTui(input) {
2031
2086
  return `full transcript (${chars})`;
2032
2087
  return `last ${argument} messages (${chars})`;
2033
2088
  }
2089
+ async function handleFeedbackSlashCommand(raw) {
2090
+ const content = raw.slice("/feedback".length).trim();
2091
+ if (!content) {
2092
+ appendBlock("[feedback]", "Usage: /feedback <message> — send free-form feedback to the Duet team", COLORS.system);
2093
+ return;
2094
+ }
2095
+ appendBlock("[feedback]", "sending…", COLORS.system);
2096
+ try {
2097
+ const { baseUrl } = await submitDuetFeedback({ content });
2098
+ appendBlock("[feedback]", `Thanks! Feedback sent to ${baseUrl}.`, COLORS.system);
2099
+ }
2100
+ catch (error) {
2101
+ appendBlock("[feedback]", error instanceof Error ? error.message : String(error), COLORS.error);
2102
+ }
2103
+ }
2034
2104
  async function handleImageSlashCommand(raw) {
2035
2105
  const rest = raw.slice("/image".length).trim();
2036
2106
  if (!rest) {