@songsid/agend 2.1.12-beta.3 → 2.1.12-beta.5

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 (110) hide show
  1. package/README.md +54 -8
  2. package/README.zh-TW.md +104 -11
  3. package/dist/agent-endpoint.d.ts +2 -0
  4. package/dist/agent-endpoint.js +38 -29
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/backend/factory.js +5 -5
  7. package/dist/backend/factory.js.map +1 -1
  8. package/dist/backend/index.d.ts +0 -1
  9. package/dist/backend/index.js +0 -1
  10. package/dist/backend/index.js.map +1 -1
  11. package/dist/backend/kiro.d.ts +10 -1
  12. package/dist/backend/kiro.js +13 -0
  13. package/dist/backend/kiro.js.map +1 -1
  14. package/dist/backend/mock.d.ts +1 -1
  15. package/dist/backend/mock.js +1 -1
  16. package/dist/backend/muse.d.ts +14 -0
  17. package/dist/backend/muse.js +60 -11
  18. package/dist/backend/muse.js.map +1 -1
  19. package/dist/backend/removed.d.ts +12 -0
  20. package/dist/backend/removed.js +18 -0
  21. package/dist/backend/removed.js.map +1 -0
  22. package/dist/backend/session-signals.js +5 -10
  23. package/dist/backend/session-signals.js.map +1 -1
  24. package/dist/backend/types.d.ts +1 -1
  25. package/dist/backend/types.js +0 -1
  26. package/dist/backend/types.js.map +1 -1
  27. package/dist/channel/adapters/discord.js +9 -0
  28. package/dist/channel/adapters/discord.js.map +1 -1
  29. package/dist/channel/adapters/telegram.d.ts +14 -8
  30. package/dist/channel/adapters/telegram.js +80 -26
  31. package/dist/channel/adapters/telegram.js.map +1 -1
  32. package/dist/channel/mcp-tools.js +2 -2
  33. package/dist/channel/mcp-tools.js.map +1 -1
  34. package/dist/classic-channel-manager.js +2 -2
  35. package/dist/classic-channel-manager.js.map +1 -1
  36. package/dist/cli.js +27 -53
  37. package/dist/cli.js.map +1 -1
  38. package/dist/command-table.d.ts +1 -1
  39. package/dist/command-table.js +4 -2
  40. package/dist/command-table.js.map +1 -1
  41. package/dist/config-validator.js +82 -10
  42. package/dist/config-validator.js.map +1 -1
  43. package/dist/config.js +7 -5
  44. package/dist/config.js.map +1 -1
  45. package/dist/context-guardian.d.ts +1 -1
  46. package/dist/context-guardian.js +1 -1
  47. package/dist/cross-instance-notice.d.ts +39 -0
  48. package/dist/cross-instance-notice.js +84 -0
  49. package/dist/cross-instance-notice.js.map +1 -0
  50. package/dist/daemon.d.ts +6 -0
  51. package/dist/daemon.js +54 -42
  52. package/dist/daemon.js.map +1 -1
  53. package/dist/daily-summary.js +0 -3
  54. package/dist/daily-summary.js.map +1 -1
  55. package/dist/fleet-manager.d.ts +16 -3
  56. package/dist/fleet-manager.js +110 -53
  57. package/dist/fleet-manager.js.map +1 -1
  58. package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -1
  59. package/dist/instance-config-impact.js +3 -0
  60. package/dist/instance-config-impact.js.map +1 -1
  61. package/dist/instance-lifecycle.d.ts +9 -1
  62. package/dist/instance-lifecycle.js +66 -7
  63. package/dist/instance-lifecycle.js.map +1 -1
  64. package/dist/locale.js +28 -2
  65. package/dist/locale.js.map +1 -1
  66. package/dist/memory-pressure.d.ts +8 -2
  67. package/dist/memory-pressure.js +10 -4
  68. package/dist/memory-pressure.js.map +1 -1
  69. package/dist/outbound-handlers.js +36 -23
  70. package/dist/outbound-handlers.js.map +1 -1
  71. package/dist/outbound-schemas.d.ts +0 -1
  72. package/dist/outbound-schemas.js +4 -4
  73. package/dist/outbound-schemas.js.map +1 -1
  74. package/dist/prompt-file-ref.d.ts +42 -0
  75. package/dist/prompt-file-ref.js +118 -0
  76. package/dist/prompt-file-ref.js.map +1 -0
  77. package/dist/reply-dedup.d.ts +5 -0
  78. package/dist/reply-dedup.js +9 -0
  79. package/dist/reply-dedup.js.map +1 -1
  80. package/dist/settings-api.js +5 -1
  81. package/dist/settings-api.js.map +1 -1
  82. package/dist/setup-wizard.js +0 -4
  83. package/dist/setup-wizard.js.map +1 -1
  84. package/dist/spawn-gate.js +4 -3
  85. package/dist/spawn-gate.js.map +1 -1
  86. package/dist/target-queue-worker.d.ts +1 -1
  87. package/dist/topic-commands.d.ts +64 -5
  88. package/dist/topic-commands.js +172 -14
  89. package/dist/topic-commands.js.map +1 -1
  90. package/dist/transcript-jsonl.d.ts +12 -0
  91. package/dist/transcript-jsonl.js +37 -0
  92. package/dist/transcript-jsonl.js.map +1 -1
  93. package/dist/transcript-monitor.js +10 -7
  94. package/dist/transcript-monitor.js.map +1 -1
  95. package/dist/transcript-sources.d.ts +1 -1
  96. package/dist/transcript-sources.js +29 -11
  97. package/dist/transcript-sources.js.map +1 -1
  98. package/dist/types.d.ts +13 -4
  99. package/dist/ui/dashboard.html +3 -3
  100. package/dist/ui/settings.html +58 -16
  101. package/dist/update-check.d.ts +15 -6
  102. package/dist/update-check.js +20 -7
  103. package/dist/update-check.js.map +1 -1
  104. package/dist/wake-coordinator.js +1 -1
  105. package/dist/web-api.js +1 -2
  106. package/dist/web-api.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/backend/gemini-cli.d.ts +0 -20
  109. package/dist/backend/gemini-cli.js +0 -169
  110. package/dist/backend/gemini-cli.js.map +0 -1
package/dist/daemon.js CHANGED
@@ -16,6 +16,8 @@ import { resolveToolSet } from "./tool-permissions.js";
16
16
  import { getAgendHome } from "./paths.js";
17
17
  import { LOGIN_FLOWS } from "./login-flows.js";
18
18
  import { ProgressAccumulator, summarizeProgress } from "./tool-progress.js";
19
+ import { assembleSystemPrompt, resolveWorkflowText } from "./prompt-file-ref.js";
20
+ import { isCrossInstanceVisibility } from "./cross-instance-notice.js";
19
21
  import { ContextGuardian } from "./context-guardian.js";
20
22
  import { IpcServer } from "./channel/ipc-bridge.js";
21
23
  import { daemonBudgetMs } from "./channel/ipc-timeouts.js";
@@ -73,9 +75,7 @@ export function buildInstructionReloadNotice(binaryName, instanceName, instanceD
73
75
  ? `.kiro/steering/agend-${instanceName}.md`
74
76
  : binaryName === "agy"
75
77
  ? ".agents/agents.md"
76
- : binaryName === "gemini"
77
- ? "GEMINI.md"
78
- : join(instanceDir, "fleet-instructions.md");
78
+ : join(instanceDir, "fleet-instructions.md");
79
79
  return `[system] Your AgEnD instructions have been updated. Reload only ${source}; do not scan other instruction directories. Do not reply to this message.`;
80
80
  }
81
81
  /**
@@ -1006,6 +1006,8 @@ export class Daemon extends EventEmitter {
1006
1006
  spawnGate;
1007
1007
  stormWindow;
1008
1008
  backendOutage;
1009
+ /** #1314: fleet-directory fallbacks already reported to the topic (once per daemon, per field and path). */
1010
+ promptFileFallbackNoticed = new Set();
1009
1011
  /** Identity of this live Daemon object; changes on object stop/restart. */
1010
1012
  bootId = randomUUID();
1011
1013
  deliveryOutbox;
@@ -2112,7 +2114,7 @@ export class Daemon extends EventEmitter {
2112
2114
  }
2113
2115
  // 8. Context guardian
2114
2116
  const statusFile = join(this.instanceDir, "statusline.json");
2115
- this.guardian = new ContextGuardian(this.config.context_guardian, this.logger, statusFile);
2117
+ this.guardian = new ContextGuardian(this.config.context_guardian ?? {}, this.logger, statusFile);
2116
2118
  this.guardian.startWatching();
2117
2119
  this.guardian.on("status_update", () => {
2118
2120
  this.saveSessionId();
@@ -3981,8 +3983,20 @@ export class Daemon extends EventEmitter {
3981
3983
  getInteractionSnapshot() {
3982
3984
  return this.interactionObservation.snapshot(this.interactionOwner());
3983
3985
  }
3986
+ /** Key of the last interaction snapshot actually emitted + broadcast (#1219). */
3987
+ lastPublishedInteractionKey = null;
3984
3988
  publishInteraction() {
3985
3989
  const interaction = this.getInteractionSnapshot();
3990
+ // The runtime monitor and every state capture observe the same unchanged
3991
+ // dialog for minutes; re-emitting an identical snapshot each time is
3992
+ // needless IPC traffic. Skip only exact duplicates — any change in the
3993
+ // presentation-relevant fields publishes, so the final state is never
3994
+ // lost (clocks like ageMs are excluded on purpose: they always change).
3995
+ const key = JSON.stringify([interaction.phase, interaction.kind, interaction.reason,
3996
+ interaction.episode, interaction.stale, interaction.suspected]);
3997
+ if (key === this.lastPublishedInteractionKey)
3998
+ return;
3999
+ this.lastPublishedInteractionKey = key;
3986
4000
  // Presentation telemetry must not interrupt the execution-state/hold path.
3987
4001
  try {
3988
4002
  this.emit("instance_interaction", { name: this.name, interaction });
@@ -5079,15 +5093,14 @@ export class Daemon extends EventEmitter {
5079
5093
  ? await this.tmux.capturePane(1_000) : await this.tmux.capturePane();
5080
5094
  if (!currentDeliveryCapture() || !sameInteractionOwner(interactionOwner, this.interactionOwner()))
5081
5095
  return;
5082
- // An old capture must not retire a new launch's transient guard either.
5083
- if (reason === "delivery_idle_gate" && !currentDeliveryCapture()) {
5084
- this.resetFooterFallback();
5085
- return;
5086
- }
5087
5096
  // Delivery's unknown-footer proof also awaits the TTY mode. Validate
5088
5097
  // output and launch freshness AFTER both awaits, before accepting it.
5089
5098
  const deliveryCandidate = reason === "delivery_idle_gate"
5090
5099
  ? await this.probeDeliveryIdleFallback(pane) : null;
5100
+ // An old capture must not retire a new launch's transient guard either.
5101
+ // This check is only live here, after the probe's await: the identical
5102
+ // check before the probe was dead (no await in between, so the early
5103
+ // return above had already settled it) and is gone (#1219).
5091
5104
  if (reason === "delivery_idle_gate" && !currentDeliveryCapture()) {
5092
5105
  this.resetFooterFallback();
5093
5106
  return;
@@ -5583,6 +5596,10 @@ export class Daemon extends EventEmitter {
5583
5596
  this.config.tags = [...update.tags];
5584
5597
  else if (update.tags === null)
5585
5598
  delete this.config.tags;
5599
+ if (isCrossInstanceVisibility(update.cross_instance_visibility))
5600
+ this.config.cross_instance_visibility = update.cross_instance_visibility;
5601
+ else if (update.cross_instance_visibility === null)
5602
+ delete this.config.cross_instance_visibility;
5586
5603
  if (["trace", "debug", "info", "warn", "error"].includes(String(update.log_level))) {
5587
5604
  const level = update.log_level;
5588
5605
  if (this.config.log_level !== level) {
@@ -8583,6 +8600,26 @@ export class Daemon extends EventEmitter {
8583
8600
  respond(null, `Unknown tool: ${tool}`);
8584
8601
  }
8585
8602
  }
8603
+ /** Where this instance's `file:` refs resolve, and what a problem with one reports — never the file's contents. */
8604
+ promptFileContext() {
8605
+ return {
8606
+ workingDirectory: this.config.working_directory,
8607
+ // The only reader of the fleet's cwd: the one-release fallback to where these refs used to resolve.
8608
+ fleetCwd: process.cwd(),
8609
+ onWarning: (warning) => {
8610
+ if (warning.problem === "fleet_dir_fallback") {
8611
+ this.logger.warn({ field: warning.field, path: warning.path, legacyPath: warning.legacyPath }, `${warning.field} file: ref is not under the instance's working directory (${warning.path}); read ${warning.legacyPath} from the fleet directory instead — make the path absolute or move the file. The fallback is removed in 2.2.`);
8612
+ const key = `${warning.field}:${warning.path}`;
8613
+ if (!this.promptFileFallbackNoticed.has(key)) {
8614
+ this.promptFileFallbackNoticed.add(key);
8615
+ this.emit("prompt_file_fallback", { name: this.name, field: warning.field, path: warning.path, legacyPath: warning.legacyPath });
8616
+ }
8617
+ return;
8618
+ }
8619
+ this.logger.warn({ field: warning.field, path: warning.path, problem: warning.problem, code: warning.code }, `${warning.field} file: ref gives nothing (${warning.problem}${warning.code ? ` ${warning.code}` : ""}): ${warning.path}`);
8620
+ },
8621
+ };
8622
+ }
8586
8623
  /** Build config object for the CLI backend */
8587
8624
  buildBackendConfig() {
8588
8625
  // Antigravity 1.1.17 has no per-workspace MCP config, but its global MCP
@@ -8595,44 +8632,19 @@ export class Daemon extends EventEmitter {
8595
8632
  serverJs = join(__dirname, "..", "dist", "channel", "mcp-server.js");
8596
8633
  }
8597
8634
  // ── Resolve workflow and systemPrompt once, share between MCP env and instructions ──
8635
+ // #1314: `file:` refs are relative to this instance's working directory (src/prompt-file-ref.ts).
8636
+ const promptFiles = this.promptFileContext();
8598
8637
  let resolvedWorkflow;
8599
8638
  if (this.config.workflow === false) {
8600
8639
  resolvedWorkflow = false;
8601
8640
  }
8602
8641
  else {
8603
8642
  const wf = this.config.workflow ?? "builtin";
8604
- if (wf !== "builtin") {
8605
- let content = wf;
8606
- if (content.startsWith("file:")) {
8607
- try {
8608
- content = readFileSync(content.slice(5), "utf-8");
8609
- }
8610
- catch {
8611
- content = "";
8612
- }
8613
- }
8614
- resolvedWorkflow = content || undefined;
8615
- }
8616
- }
8617
- let resolvedCustomPrompt;
8618
- if (this.config.systemPrompt) {
8619
- // Support comma-separated file: paths for prompt modularization:
8620
- // systemPrompt: "file:prompts/role.md, file:prompts/rules.md, file:prompts/context.md"
8621
- const parts = this.config.systemPrompt.split(",").map((s) => s.trim());
8622
- const resolved = parts.map((part) => {
8623
- if (part.startsWith("file:")) {
8624
- try {
8625
- return readFileSync(part.slice(5), "utf-8");
8626
- }
8627
- catch {
8628
- return "";
8629
- }
8630
- }
8631
- return part;
8632
- }).filter(Boolean);
8633
- if (resolved.length > 0)
8634
- resolvedCustomPrompt = resolved.join("\n\n");
8643
+ if (wf !== "builtin")
8644
+ resolvedWorkflow = resolveWorkflowText(wf, promptFiles) || undefined;
8635
8645
  }
8646
+ // Comma-separated parts (`file:role.md, file:rules.md`) only when a part is a file ref; otherwise one inline prompt.
8647
+ const resolvedCustomPrompt = this.config.systemPrompt ? assembleSystemPrompt(this.config.systemPrompt, promptFiles) : undefined;
8636
8648
  let decisions;
8637
8649
  if (process.env.AGEND_DECISIONS) {
8638
8650
  try {
@@ -9494,8 +9506,8 @@ export class Daemon extends EventEmitter {
9494
9506
  else {
9495
9507
  this.warmupNeeded = !!backendConfig.instructions && prev !== backendConfig.instructions;
9496
9508
  }
9497
- // For backends that don't re-read instructions on resume (kiro/codex/
9498
- // gemini), also notify the agent on next message instead of forcing a new
9509
+ // For backends that don't re-read instructions on resume (kiro/codex),
9510
+ // also notify the agent on next message instead of forcing a new
9499
9511
  // session. Resume is preserved so context isn't lost.
9500
9512
  if (!backendConfig.skipResume && backendNeedsPaneReloadNotice(this.backend) && this.warmupNeeded) {
9501
9513
  if (prev) {