@botcord/daemon 0.2.5 → 0.2.8

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 (88) hide show
  1. package/dist/agent-discovery.d.ts +4 -0
  2. package/dist/agent-discovery.js +8 -0
  3. package/dist/agent-workspace.d.ts +62 -0
  4. package/dist/agent-workspace.js +140 -8
  5. package/dist/config.d.ts +64 -1
  6. package/dist/config.js +73 -1
  7. package/dist/daemon-config-map.d.ts +27 -9
  8. package/dist/daemon-config-map.js +105 -8
  9. package/dist/daemon.d.ts +2 -0
  10. package/dist/daemon.js +76 -6
  11. package/dist/doctor.d.ts +27 -1
  12. package/dist/doctor.js +22 -1
  13. package/dist/gateway/cli-resolver.d.ts +34 -0
  14. package/dist/gateway/cli-resolver.js +74 -0
  15. package/dist/gateway/dispatcher.d.ts +31 -1
  16. package/dist/gateway/dispatcher.js +337 -29
  17. package/dist/gateway/gateway.d.ts +29 -1
  18. package/dist/gateway/gateway.js +10 -0
  19. package/dist/gateway/index.d.ts +2 -0
  20. package/dist/gateway/index.js +2 -0
  21. package/dist/gateway/policy-resolver.d.ts +57 -0
  22. package/dist/gateway/policy-resolver.js +123 -0
  23. package/dist/gateway/runtimes/acp-stream.d.ts +99 -0
  24. package/dist/gateway/runtimes/acp-stream.js +394 -0
  25. package/dist/gateway/runtimes/codex.js +7 -0
  26. package/dist/gateway/runtimes/hermes-agent.d.ts +83 -0
  27. package/dist/gateway/runtimes/hermes-agent.js +180 -0
  28. package/dist/gateway/runtimes/ndjson-stream.d.ts +7 -2
  29. package/dist/gateway/runtimes/ndjson-stream.js +16 -3
  30. package/dist/gateway/runtimes/openclaw-acp.d.ts +44 -0
  31. package/dist/gateway/runtimes/openclaw-acp.js +500 -0
  32. package/dist/gateway/runtimes/registry.d.ts +4 -0
  33. package/dist/gateway/runtimes/registry.js +22 -0
  34. package/dist/gateway/transcript-paths.d.ts +30 -0
  35. package/dist/gateway/transcript-paths.js +114 -0
  36. package/dist/gateway/transcript.d.ts +123 -0
  37. package/dist/gateway/transcript.js +147 -0
  38. package/dist/gateway/types.d.ts +31 -0
  39. package/dist/index.js +309 -27
  40. package/dist/mention-scan.d.ts +22 -0
  41. package/dist/mention-scan.js +35 -0
  42. package/dist/openclaw-discovery.d.ts +28 -0
  43. package/dist/openclaw-discovery.js +228 -0
  44. package/dist/provision.d.ts +113 -1
  45. package/dist/provision.js +564 -12
  46. package/dist/system-context.d.ts +5 -4
  47. package/dist/system-context.js +35 -5
  48. package/dist/url-utils.d.ts +9 -0
  49. package/dist/url-utils.js +18 -0
  50. package/package.json +3 -2
  51. package/src/__tests__/agent-workspace.test.ts +93 -0
  52. package/src/__tests__/daemon-config-map.test.ts +79 -0
  53. package/src/__tests__/openclaw-acp.test.ts +234 -0
  54. package/src/__tests__/openclaw-discovery.test.ts +150 -0
  55. package/src/__tests__/policy-resolver.test.ts +124 -0
  56. package/src/__tests__/policy-updated-handler.test.ts +144 -0
  57. package/src/__tests__/provision.test.ts +265 -0
  58. package/src/__tests__/system-context.test.ts +52 -0
  59. package/src/__tests__/url-utils.test.ts +37 -0
  60. package/src/agent-discovery.ts +8 -0
  61. package/src/agent-workspace.ts +173 -7
  62. package/src/config.ts +168 -4
  63. package/src/daemon-config-map.ts +154 -9
  64. package/src/daemon.ts +96 -6
  65. package/src/doctor.ts +49 -2
  66. package/src/gateway/__tests__/dispatcher.test.ts +65 -0
  67. package/src/gateway/__tests__/hermes-agent-adapter.test.ts +302 -0
  68. package/src/gateway/__tests__/transcript.test.ts +496 -0
  69. package/src/gateway/cli-resolver.ts +92 -0
  70. package/src/gateway/dispatcher.ts +394 -26
  71. package/src/gateway/gateway.ts +46 -0
  72. package/src/gateway/index.ts +25 -0
  73. package/src/gateway/policy-resolver.ts +171 -0
  74. package/src/gateway/runtimes/acp-stream.ts +535 -0
  75. package/src/gateway/runtimes/codex.ts +7 -0
  76. package/src/gateway/runtimes/hermes-agent.ts +206 -0
  77. package/src/gateway/runtimes/ndjson-stream.ts +16 -3
  78. package/src/gateway/runtimes/openclaw-acp.ts +606 -0
  79. package/src/gateway/runtimes/registry.ts +24 -0
  80. package/src/gateway/transcript-paths.ts +145 -0
  81. package/src/gateway/transcript.ts +300 -0
  82. package/src/gateway/types.ts +32 -0
  83. package/src/index.ts +321 -30
  84. package/src/mention-scan.ts +38 -0
  85. package/src/openclaw-discovery.ts +262 -0
  86. package/src/provision.ts +682 -14
  87. package/src/system-context.ts +41 -9
  88. package/src/url-utils.ts +17 -0
@@ -6,10 +6,11 @@
6
6
  * `RuntimeRunOptions.systemContext`. This module composes the daemon's
7
7
  * system-context string from:
8
8
  *
9
- * 1. `[BotCord Scene: Owner Chat]` (owner-trust turns only)
10
- * 2. `[BotCord Working Memory]`
11
- * 3. `[BotCord Room Context]` (group rooms, via optional async fetcher)
12
- * 4. `[BotCord Cross-Room Awareness]` (optional activity tracker)
9
+ * 1. `[BotCord Identity]` (read fresh from workspace/identity.md each turn)
10
+ * 2. `[BotCord Scene: Owner Chat]` (owner-trust turns only)
11
+ * 3. `[BotCord Working Memory]`
12
+ * 4. `[BotCord Room Context]` (group rooms, via optional async fetcher)
13
+ * 5. `[BotCord Cross-Room Awareness]` (optional activity tracker)
13
14
  *
14
15
  * Behavior:
15
16
  * - Working memory is loaded fresh per turn, so a `memory set` from another
@@ -26,6 +27,7 @@ import type { GatewayInboundMessage, SystemContextBuilder } from "./gateway/inde
26
27
  import type { ActivityTracker } from "./activity-tracker.js";
27
28
  import { buildCrossRoomDigest } from "./cross-room.js";
28
29
  import { buildWorkingMemoryPrompt, readWorkingMemory } from "./working-memory.js";
30
+ import { readIdentity } from "./agent-workspace.js";
29
31
  import { classifyActivitySender } from "./sender-classify.js";
30
32
  import { log } from "./log.js";
31
33
 
@@ -86,6 +88,31 @@ function safeReadWorkingMemory(agentId: string) {
86
88
  }
87
89
  }
88
90
 
91
+ /**
92
+ * Read identity.md and wrap it as a system-context block. Placed before
93
+ * every other block so the agent answers "who are you" from this file
94
+ * rather than from the underlying CLI's default persona ("I am Claude
95
+ * Code"). Re-read every turn so dashboard reconcile (`applyAgentIdentity`)
96
+ * and self-edits take effect immediately, mirroring working-memory
97
+ * semantics.
98
+ */
99
+ function buildIdentityPrompt(agentId: string): string | null {
100
+ let raw: string | null = null;
101
+ try {
102
+ raw = readIdentity(agentId);
103
+ } catch (err) {
104
+ log.warn("identity read failed", { agentId, err: String(err) });
105
+ return null;
106
+ }
107
+ if (!raw) return null;
108
+ return [
109
+ "[BotCord Identity]",
110
+ "Your persistent identity card. The fields below are the source of truth — when asked who you are, what you do, or what you will / will not do, answer from this block, not from the underlying CLI's default persona.",
111
+ "",
112
+ raw.trim(),
113
+ ].join("\n");
114
+ }
115
+
89
116
  /**
90
117
  * Build a {@link SystemContextBuilder} for the gateway dispatcher.
91
118
  *
@@ -97,10 +124,13 @@ export function createDaemonSystemContextBuilder(
97
124
  deps: SystemContextDeps,
98
125
  ): (message: GatewayInboundMessage) => Promise<string | undefined> | string | undefined {
99
126
  const gatherSyncBlocks = (message: GatewayInboundMessage): {
127
+ identity: string | null;
100
128
  ownerScene: string | null;
101
129
  memory: string | null;
102
130
  digest: string | null;
103
131
  } => {
132
+ const identity = buildIdentityPrompt(deps.agentId);
133
+
104
134
  const ownerScene =
105
135
  classifyActivitySender(message).kind === "owner"
106
136
  ? buildOwnerChatSceneContext()
@@ -118,7 +148,7 @@ export function createDaemonSystemContextBuilder(
118
148
  }) || null
119
149
  : null;
120
150
 
121
- return { ownerScene, memory, digest };
151
+ return { identity, ownerScene, memory, digest };
122
152
  };
123
153
 
124
154
  const assemble = (parts: Array<string | null | undefined>): string | undefined => {
@@ -144,11 +174,12 @@ export function createDaemonSystemContextBuilder(
144
174
 
145
175
  if (!deps.roomContextBuilder) {
146
176
  const syncBuilder = (message: GatewayInboundMessage): string | undefined => {
147
- const { ownerScene, memory, digest } = gatherSyncBlocks(message);
177
+ const { identity, ownerScene, memory, digest } = gatherSyncBlocks(message);
148
178
  // Loop-risk sits at the end so its "reply NO_REPLY unless…" guidance
149
179
  // is the last thing the model sees before the user turn body.
180
+ // Identity sits at the very front so it frames every other block.
150
181
  const loopRisk = runLoopRisk(message);
151
- return assemble([ownerScene, memory, digest, loopRisk]);
182
+ return assemble([identity, ownerScene, memory, digest, loopRisk]);
152
183
  };
153
184
  // Compile-time witness that the narrower sync signature still satisfies
154
185
  // `SystemContextBuilder` (which allows async). Prevents the two contracts
@@ -162,11 +193,12 @@ export function createDaemonSystemContextBuilder(
162
193
  const asyncBuilder = async (
163
194
  message: GatewayInboundMessage,
164
195
  ): Promise<string | undefined> => {
165
- const { ownerScene, memory, digest } = gatherSyncBlocks(message);
196
+ const { identity, ownerScene, memory, digest } = gatherSyncBlocks(message);
166
197
  // Room context landing order: after owner-scene / memory, before digest —
167
198
  // "what room am I in" belongs with the session's own identity, while the
168
199
  // cross-room digest deliberately describes OTHER rooms and should stay
169
200
  // last so it doesn't get confused with the current room.
201
+ // Identity stays at the very front; see syncBuilder for rationale.
170
202
  let roomBlock: string | null = null;
171
203
  try {
172
204
  roomBlock = await roomBuilder(message);
@@ -178,7 +210,7 @@ export function createDaemonSystemContextBuilder(
178
210
  });
179
211
  }
180
212
  const loopRisk = runLoopRisk(message);
181
- return assemble([ownerScene, memory, roomBlock, digest, loopRisk]);
213
+ return assemble([identity, ownerScene, memory, roomBlock, digest, loopRisk]);
182
214
  };
183
215
  const _typecheck: SystemContextBuilder = asyncBuilder;
184
216
  void _typecheck;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Append a `next` query param to a URL. Used by the device-code flow to
3
+ * encode a post-auth redirect target into the Hub-issued verification URL,
4
+ * so the dashboard knows where to send the user after they click Authorize.
5
+ *
6
+ * Falls back to returning the original URL string if parsing fails — the
7
+ * device-code flow keeps working, just without the redirect convenience.
8
+ */
9
+ export function appendNextParam(url: string, next: string): string {
10
+ try {
11
+ const u = new URL(url);
12
+ u.searchParams.set("next", next);
13
+ return u.toString();
14
+ } catch {
15
+ return url;
16
+ }
17
+ }