instar 1.2.67 → 1.2.68
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +50 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +12 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +138 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +3 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.d.ts.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.js +1 -0
- package/dist/providers/adapters/anthropic-headless/transport/agenticSessionHeadless.js.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.js +1 -0
- package/dist/providers/adapters/openai-codex/transport/agenticSessionHeadless.js.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.d.ts +2 -0
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.d.ts.map +1 -1
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.js +4 -0
- package/dist/providers/adapters/openai-codex/transport/codexSpawn.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +6 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +60 -1
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/ConversationStore.d.ts +158 -0
- package/dist/threadline/ConversationStore.d.ts.map +1 -0
- package/dist/threadline/ConversationStore.js +341 -0
- package/dist/threadline/ConversationStore.js.map +1 -0
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +24 -0
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/WarrantsReplyGate.d.ts +110 -0
- package/dist/threadline/WarrantsReplyGate.d.ts.map +1 -0
- package/dist/threadline/WarrantsReplyGate.js +263 -0
- package/dist/threadline/WarrantsReplyGate.js.map +1 -0
- package/dist/threadline/mcp-http-client.d.ts.map +1 -1
- package/dist/threadline/mcp-http-client.js +6 -0
- package/dist/threadline/mcp-http-client.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/upgrades/1.2.68.md +97 -0
|
@@ -104,6 +104,18 @@ export declare class PostUpdateMigrator {
|
|
|
104
104
|
*/
|
|
105
105
|
private migrateBootWrapperAbiCheck;
|
|
106
106
|
private migrateStaleLifelineSignal;
|
|
107
|
+
/**
|
|
108
|
+
* Threadline Phase 1 keystone (THREADLINE-CONVERSATION-KEYSTONE-SPEC, Migration
|
|
109
|
+
* parity): fold the legacy thread-resume-map.json + context-thread-map.json
|
|
110
|
+
* into the unified conversations.json so in-flight conversations survive the
|
|
111
|
+
* update with their turn/binding context. Idempotent (skips a threadId already
|
|
112
|
+
* present in conversations.json — never clobbers runtime-written rows),
|
|
113
|
+
* atomic (tmp + rename), and field-preserving (sessionUuid, agentIdentity,
|
|
114
|
+
* pinned, lifecycle incl. failed/archived, cross-machine fields). Reconciliation
|
|
115
|
+
* rule: the resume entry is authoritative for session binding; the contextId
|
|
116
|
+
* index is attached from the context map (distinct fields, no conflict).
|
|
117
|
+
*/
|
|
118
|
+
private migrateThreadlineConversationStore;
|
|
107
119
|
private migrateBootWrapperToCjs;
|
|
108
120
|
private migrateConversationalCatalogPlaybookManifest;
|
|
109
121
|
private migrateWorktreeConvention;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAkCH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAIjC,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,CAAiC;gBAEvC,MAAM,EAAE,cAAc;IAIlC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAItC;;;;;;OAMG;IACG,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC;IAIjC,OAAO,CAAC,aAAa;IAOrB;;;OAGG;IACH,OAAO,IAAI,eAAe;
|
|
1
|
+
{"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -156,6 +156,7 @@ export class PostUpdateMigrator {
|
|
|
156
156
|
this.migrateBootWrapperToCjs(result);
|
|
157
157
|
this.migrateBootWrapperAbiCheck(result);
|
|
158
158
|
this.migrateStaleLifelineSignal(result);
|
|
159
|
+
this.migrateThreadlineConversationStore(result);
|
|
159
160
|
return result;
|
|
160
161
|
}
|
|
161
162
|
/**
|
|
@@ -289,6 +290,143 @@ export class PostUpdateMigrator {
|
|
|
289
290
|
result.errors.push(`stale-lifeline-signal: ${err instanceof Error ? err.message : String(err)}`);
|
|
290
291
|
}
|
|
291
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Threadline Phase 1 keystone (THREADLINE-CONVERSATION-KEYSTONE-SPEC, Migration
|
|
295
|
+
* parity): fold the legacy thread-resume-map.json + context-thread-map.json
|
|
296
|
+
* into the unified conversations.json so in-flight conversations survive the
|
|
297
|
+
* update with their turn/binding context. Idempotent (skips a threadId already
|
|
298
|
+
* present in conversations.json — never clobbers runtime-written rows),
|
|
299
|
+
* atomic (tmp + rename), and field-preserving (sessionUuid, agentIdentity,
|
|
300
|
+
* pinned, lifecycle incl. failed/archived, cross-machine fields). Reconciliation
|
|
301
|
+
* rule: the resume entry is authoritative for session binding; the contextId
|
|
302
|
+
* index is attached from the context map (distinct fields, no conflict).
|
|
303
|
+
*/
|
|
304
|
+
migrateThreadlineConversationStore(result) {
|
|
305
|
+
const dir = path.join(this.config.stateDir, 'threadline');
|
|
306
|
+
const resumePath = path.join(dir, 'thread-resume-map.json');
|
|
307
|
+
const ctxPath = path.join(dir, 'context-thread-map.json');
|
|
308
|
+
const convPath = path.join(dir, 'conversations.json');
|
|
309
|
+
if (!fs.existsSync(resumePath) && !fs.existsSync(ctxPath)) {
|
|
310
|
+
result.skipped.push('threadline-conversations: no legacy stores to fold');
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
// Load existing unified store (idempotency — never overwrite live rows).
|
|
314
|
+
let store;
|
|
315
|
+
try {
|
|
316
|
+
if (fs.existsSync(convPath)) {
|
|
317
|
+
const parsed = JSON.parse(fs.readFileSync(convPath, 'utf-8'));
|
|
318
|
+
store = (parsed && parsed.version === 1 && parsed.conversations)
|
|
319
|
+
? parsed
|
|
320
|
+
: { version: 1, conversations: {}, lastModified: new Date().toISOString() };
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
store = { version: 1, conversations: {}, lastModified: new Date().toISOString() };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
store = { version: 1, conversations: {}, lastModified: new Date().toISOString() };
|
|
328
|
+
}
|
|
329
|
+
const now = new Date().toISOString();
|
|
330
|
+
let folded = 0;
|
|
331
|
+
// 1) Fold ThreadResumeMap entries (authoritative for session binding).
|
|
332
|
+
try {
|
|
333
|
+
if (fs.existsSync(resumePath)) {
|
|
334
|
+
const resumeMap = JSON.parse(fs.readFileSync(resumePath, 'utf-8'));
|
|
335
|
+
for (const [threadId, e] of Object.entries(resumeMap)) {
|
|
336
|
+
if (!threadId || typeof e !== 'object' || e === null)
|
|
337
|
+
continue;
|
|
338
|
+
if (store.conversations[threadId])
|
|
339
|
+
continue; // idempotent — keep live row
|
|
340
|
+
const remoteAgent = typeof e.remoteAgent === 'string' ? e.remoteAgent : undefined;
|
|
341
|
+
store.conversations[threadId] = {
|
|
342
|
+
threadId,
|
|
343
|
+
version: 0,
|
|
344
|
+
participants: { peers: remoteAgent ? [remoteAgent] : [] },
|
|
345
|
+
remoteAgent,
|
|
346
|
+
state: typeof e.state === 'string' ? e.state : 'idle',
|
|
347
|
+
resolvedAt: e.resolvedAt,
|
|
348
|
+
sessionUuid: typeof e.uuid === 'string' ? e.uuid : undefined,
|
|
349
|
+
boundSessionName: typeof e.sessionName === 'string' ? e.sessionName : undefined,
|
|
350
|
+
boundTopicId: typeof e.originTopicId === 'number' ? e.originTopicId : undefined,
|
|
351
|
+
originSessionName: typeof e.originSessionName === 'string' ? e.originSessionName : undefined,
|
|
352
|
+
spawnMode: e.spawnMode,
|
|
353
|
+
subject: typeof e.subject === 'string' ? e.subject : undefined,
|
|
354
|
+
pinned: e.pinned === true,
|
|
355
|
+
messageCount: typeof e.messageCount === 'number' ? e.messageCount : 0,
|
|
356
|
+
machineOrigin: e.machineOrigin,
|
|
357
|
+
migratedTo: e.migratedTo,
|
|
358
|
+
turnCount: 0,
|
|
359
|
+
createdAt: typeof e.createdAt === 'string' ? e.createdAt : now,
|
|
360
|
+
savedAt: now,
|
|
361
|
+
lastActivityAt: typeof e.lastAccessedAt === 'string' ? e.lastAccessedAt : now,
|
|
362
|
+
};
|
|
363
|
+
folded++;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
result.errors.push(`threadline-conversations resume fold: ${err instanceof Error ? err.message : String(err)}`);
|
|
369
|
+
}
|
|
370
|
+
// 2) Attach ContextThreadMap identity bindings (reconciliation: resume entry
|
|
371
|
+
// is authoritative for session binding; contextId index rebuilt from here).
|
|
372
|
+
try {
|
|
373
|
+
if (fs.existsSync(ctxPath)) {
|
|
374
|
+
const ctxFile = JSON.parse(fs.readFileSync(ctxPath, 'utf-8'));
|
|
375
|
+
const mappings = Array.isArray(ctxFile.mappings) ? ctxFile.mappings : [];
|
|
376
|
+
for (const m of mappings) {
|
|
377
|
+
const threadId = typeof m.threadId === 'string' ? m.threadId : undefined;
|
|
378
|
+
if (!threadId)
|
|
379
|
+
continue;
|
|
380
|
+
const existing = store.conversations[threadId];
|
|
381
|
+
if (existing) {
|
|
382
|
+
if (existing.contextId === undefined && typeof m.contextId === 'string')
|
|
383
|
+
existing.contextId = m.contextId;
|
|
384
|
+
if (existing.agentIdentity === undefined && typeof m.agentIdentity === 'string')
|
|
385
|
+
existing.agentIdentity = m.agentIdentity;
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
// Context-only thread (no resume entry) — create a minimal row so the
|
|
389
|
+
// identity binding (hijack guard) is not lost.
|
|
390
|
+
store.conversations[threadId] = {
|
|
391
|
+
threadId, version: 0, participants: { peers: [] },
|
|
392
|
+
state: 'idle', pinned: false, messageCount: 0, turnCount: 0,
|
|
393
|
+
contextId: typeof m.contextId === 'string' ? m.contextId : undefined,
|
|
394
|
+
agentIdentity: typeof m.agentIdentity === 'string' ? m.agentIdentity : undefined,
|
|
395
|
+
createdAt: typeof m.createdAt === 'string' ? m.createdAt : now,
|
|
396
|
+
savedAt: now,
|
|
397
|
+
lastActivityAt: typeof m.lastAccessedAt === 'string' ? m.lastAccessedAt : now,
|
|
398
|
+
};
|
|
399
|
+
folded++;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
result.errors.push(`threadline-conversations context fold: ${err instanceof Error ? err.message : String(err)}`);
|
|
406
|
+
}
|
|
407
|
+
if (folded === 0) {
|
|
408
|
+
result.skipped.push('threadline-conversations: nothing new to fold (already migrated)');
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
// Atomic write (backup + tmp + rename).
|
|
412
|
+
try {
|
|
413
|
+
store.lastModified = now;
|
|
414
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
415
|
+
if (fs.existsSync(convPath)) {
|
|
416
|
+
try {
|
|
417
|
+
fs.copyFileSync(convPath, `${convPath}.bak`);
|
|
418
|
+
}
|
|
419
|
+
catch { /* best-effort backup */ }
|
|
420
|
+
}
|
|
421
|
+
const tmp = `${convPath}.migrate-${process.pid}-${Date.now()}.tmp`;
|
|
422
|
+
fs.writeFileSync(tmp, JSON.stringify(store, null, 2) + '\n');
|
|
423
|
+
fs.renameSync(tmp, convPath);
|
|
424
|
+
result.upgraded.push(`threadline-conversations: folded ${folded} legacy thread(s) into conversations.json`);
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
result.errors.push(`threadline-conversations write: ${err instanceof Error ? err.message : String(err)}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
292
430
|
migrateBootWrapperToCjs(result) {
|
|
293
431
|
if (process.platform !== 'darwin') {
|
|
294
432
|
result.skipped.push('boot-wrapper .cjs: non-darwin, no plist to migrate');
|