@keyou007/agent-bot 0.1.16-alpha.4 → 0.1.17-alpha.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 (45) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +4 -2
  3. package/README.zh.md +4 -2
  4. package/config.example.yaml +8 -0
  5. package/dist/cli/help.js +4 -4
  6. package/dist/cli/taskTarget.js +7 -0
  7. package/dist/cli/taskTarget.js.map +1 -1
  8. package/dist/cli.js +12 -12
  9. package/dist/cli.js.map +1 -1
  10. package/dist/codex/CodexRuntime.js +40 -12
  11. package/dist/codex/CodexRuntime.js.map +1 -1
  12. package/dist/config/AgentExecutionDefaultsStore.js +71 -0
  13. package/dist/config/AgentExecutionDefaultsStore.js.map +1 -0
  14. package/dist/config/loadConfig.js +8 -0
  15. package/dist/config/loadConfig.js.map +1 -1
  16. package/dist/config/schema.js +7 -0
  17. package/dist/config/schema.js.map +1 -1
  18. package/dist/feishu/CardRenderer.js +29 -27
  19. package/dist/feishu/CardRenderer.js.map +1 -1
  20. package/dist/index.js +17 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/proxy/ProxySessionController.js +255 -30
  23. package/dist/proxy/ProxySessionController.js.map +1 -1
  24. package/dist/state/StateStore.js +62 -9
  25. package/dist/state/StateStore.js.map +1 -1
  26. package/dist/supervision/restartNotificationTarget.js +9 -0
  27. package/dist/supervision/restartNotificationTarget.js.map +1 -0
  28. package/docs/technical-reference.md +7 -3
  29. package/docs/technical-reference.zh.md +7 -3
  30. package/npm-shrinkwrap.json +2 -2
  31. package/package.json +1 -1
  32. package/skills/agent-bot/SKILL.md +3 -1
  33. package/src/cli/help.ts +4 -4
  34. package/src/cli/taskTarget.ts +11 -0
  35. package/src/cli.ts +16 -20
  36. package/src/codex/CodexRuntime.ts +38 -10
  37. package/src/config/AgentExecutionDefaultsStore.ts +71 -0
  38. package/src/config/loadConfig.ts +8 -0
  39. package/src/config/schema.ts +13 -1
  40. package/src/feishu/CardRenderer.ts +30 -22
  41. package/src/index.ts +17 -2
  42. package/src/proxy/ProxySessionController.ts +330 -40
  43. package/src/runtime/types.ts +8 -0
  44. package/src/state/StateStore.ts +100 -9
  45. package/src/supervision/restartNotificationTarget.ts +12 -0
@@ -95,6 +95,23 @@ export interface CompletedTurnSnapshotRecord {
95
95
  updatedAt: string;
96
96
  }
97
97
 
98
+ export interface ImportedCompletedTurnRecord {
99
+ turnId: string;
100
+ snapshot: unknown;
101
+ updatedAt: string;
102
+ }
103
+
104
+ export interface ForkHistorySourceRecord {
105
+ sourceLocalSessionId?: string;
106
+ sourceRemoteSessionId?: string;
107
+ sourceTurnId: string;
108
+ sourceTurnPrompt?: string;
109
+ sourceTurnStartedAt?: number;
110
+ sourceTurnCompletedAt?: number;
111
+ sourceTurnHistoryCount?: number;
112
+ createdAt: string;
113
+ }
114
+
98
115
  export interface QueuedPromptRecord {
99
116
  promptId: string;
100
117
  localSessionId: string;
@@ -1091,6 +1108,45 @@ export class StateStore {
1091
1108
  `).run(turnId, localSessionId, parentTurnId ?? null, new Date().toISOString());
1092
1109
  }
1093
1110
 
1111
+ importCompletedTurnHistory(input: {
1112
+ localSessionId: string;
1113
+ contextKey: string;
1114
+ agentName: string;
1115
+ remoteSessionId: string;
1116
+ turns: ImportedCompletedTurnRecord[];
1117
+ }): void {
1118
+ const importHistory = this.db.transaction(() => {
1119
+ let parentTurnId: string | undefined;
1120
+ for (const turn of input.turns) {
1121
+ this.db.prepare(`
1122
+ INSERT OR IGNORE INTO turn_snapshots (
1123
+ turn_id, local_session_id, context_key, snapshot_json, updated_at
1124
+ ) VALUES (?, ?, ?, ?, ?)
1125
+ `).run(
1126
+ turn.turnId,
1127
+ input.localSessionId,
1128
+ input.contextKey,
1129
+ JSON.stringify(turn.snapshot),
1130
+ turn.updatedAt,
1131
+ );
1132
+ this.db.prepare(`
1133
+ INSERT OR IGNORE INTO turn_runtime_origins (
1134
+ turn_id, local_session_id, agent_name, remote_session_id, created_at
1135
+ ) VALUES (?, ?, ?, ?, ?)
1136
+ `).run(
1137
+ turn.turnId,
1138
+ input.localSessionId,
1139
+ input.agentName,
1140
+ input.remoteSessionId,
1141
+ turn.updatedAt,
1142
+ );
1143
+ this.saveTurnParent(turn.turnId, input.localSessionId, parentTurnId);
1144
+ parentTurnId = turn.turnId;
1145
+ }
1146
+ });
1147
+ importHistory();
1148
+ }
1149
+
1094
1150
  getTurnParent(turnId: string, localSessionId: string): string | undefined {
1095
1151
  const row = this.db.prepare(`
1096
1152
  SELECT parent_turn_id
@@ -1219,6 +1275,41 @@ export class StateStore {
1219
1275
  return [...records.values()].sort(compareCompletedTurnSnapshots);
1220
1276
  }
1221
1277
 
1278
+ getForkHistorySource(localSessionId: string): ForkHistorySourceRecord | undefined {
1279
+ const row = this.db.prepare(`
1280
+ SELECT payload_json, created_at
1281
+ FROM audit_events
1282
+ WHERE event_type IN ('session_forked', 'thread_forked')
1283
+ AND json_extract(payload_json, '$.forkedLocalSessionId') = ?
1284
+ ORDER BY id DESC
1285
+ LIMIT 1
1286
+ `).get(localSessionId) as { payload_json: string; created_at: string } | undefined;
1287
+ if (!row) return undefined;
1288
+ const payload = JSON.parse(row.payload_json) as Record<string, unknown>;
1289
+ const sourceTurnId = stringValue(payload.sourceTurnId);
1290
+ if (!sourceTurnId) return undefined;
1291
+ return {
1292
+ sourceLocalSessionId: stringValue(payload.sourceLocalSessionId),
1293
+ sourceRemoteSessionId: stringValue(payload.sourceRemoteSessionId),
1294
+ sourceTurnId,
1295
+ sourceTurnPrompt: stringValue(payload.sourceTurnPrompt),
1296
+ sourceTurnStartedAt: numberValue(payload.sourceTurnStartedAt),
1297
+ sourceTurnCompletedAt: numberValue(payload.sourceTurnCompletedAt),
1298
+ sourceTurnHistoryCount: numberValue(payload.sourceTurnHistoryCount),
1299
+ createdAt: row.created_at,
1300
+ };
1301
+ }
1302
+
1303
+ hasImportedForkTurnHistory(localSessionId: string): boolean {
1304
+ return Boolean(this.db.prepare(`
1305
+ SELECT 1
1306
+ FROM audit_events
1307
+ WHERE event_type = 'fork_turn_history_imported'
1308
+ AND json_extract(payload_json, '$.forkedLocalSessionId') = ?
1309
+ LIMIT 1
1310
+ `).get(localSessionId));
1311
+ }
1312
+
1222
1313
  private listCompletedTurnGraphRows(localSessionId: string): CompletedTurnSnapshotRecord[] {
1223
1314
  const rows = this.db.prepare(`
1224
1315
  SELECT ts.turn_id, tpl.parent_turn_id, ts.snapshot_json, ts.updated_at
@@ -1260,15 +1351,7 @@ export class StateStore {
1260
1351
  }
1261
1352
 
1262
1353
  private findForkSourceTurnId(localSessionId: string): string | undefined {
1263
- const row = this.db.prepare(`
1264
- SELECT json_extract(payload_json, '$.sourceTurnId') AS source_turn_id
1265
- FROM audit_events
1266
- WHERE event_type IN ('session_forked', 'thread_forked')
1267
- AND json_extract(payload_json, '$.forkedLocalSessionId') = ?
1268
- ORDER BY id DESC
1269
- LIMIT 1
1270
- `).get(localSessionId) as { source_turn_id: string | null } | undefined;
1271
- return row?.source_turn_id ?? undefined;
1354
+ return this.getForkHistorySource(localSessionId)?.sourceTurnId;
1272
1355
  }
1273
1356
 
1274
1357
  private findCrossSessionParentTurnId(localSessionId: string): string | undefined {
@@ -2189,6 +2272,14 @@ function completedTurnTimestamp(record: CompletedTurnSnapshotRecord): number {
2189
2272
  return Number.isFinite(timestamp) ? timestamp : 0;
2190
2273
  }
2191
2274
 
2275
+ function stringValue(value: unknown): string | undefined {
2276
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
2277
+ }
2278
+
2279
+ function numberValue(value: unknown): number | undefined {
2280
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
2281
+ }
2282
+
2192
2283
  function isIncompleteTurnAttemptStatus(status: TurnAttemptStatus): boolean {
2193
2284
  return status === "accepted" || status === "running" || status === "recovering";
2194
2285
  }
@@ -0,0 +1,12 @@
1
+ import type { RestartNotificationTarget } from "./SafeRestartScheduler.js";
2
+
3
+ export function privateRestartNotificationTarget(userOpenId: string | undefined): RestartNotificationTarget {
4
+ const normalizedUserOpenId = userOpenId?.trim();
5
+ if (!normalizedUserOpenId) {
6
+ throw new Error(
7
+ "Cannot send CLI restart notifications to private chat because feishu.userOpenId is not configured. "
8
+ + "Run agentbot init or pass --task <task>.",
9
+ );
10
+ }
11
+ return { contextKey: `open_id:${normalizedUserOpenId}` };
12
+ }