@playcraft/cli 0.1.17 → 0.1.19

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.
@@ -8,7 +8,6 @@ import { portableCodexConfig, writePortableCodexCatalog } from './config-toml.js
8
8
  import { createJsonRpcStdioClient } from './jsonrpc-stdio.js';
9
9
  import { projectNativeThread } from '@playcraft/common/cloud-workspace/runtime';
10
10
  import { collectedEvent, NativePreparationError } from './native-adapter.js';
11
- import { exportTranscript } from './transcripts.js';
12
11
  import { readProjectSkillsLockFile } from '@playcraft/common/project-skills';
13
12
  import { freezeWorkspaceSkills } from '../workspaces/skills.js';
14
13
  function asRecord(value) {
@@ -75,18 +74,6 @@ export function createCodexAppServerAdapter(options) {
75
74
  release();
76
75
  }
77
76
  }
78
- function transcriptHome() {
79
- if (!launcherSocket)
80
- return { homeDir };
81
- return {
82
- homeDir,
83
- launcher: {
84
- socketPath: launcherSocket,
85
- runtimeEpoch: executionEpoch,
86
- cwd: options.config.workspaceMode === 'multi' ? '/home/playcraft-dev' : options.config.workspaceRoot,
87
- },
88
- };
89
- }
90
77
  async function ensureStarted() {
91
78
  if (closed)
92
79
  throw new Error('codex_not_started');
@@ -382,44 +369,6 @@ export function createCodexAppServerAdapter(options) {
382
369
  throw new Error('codex_not_started');
383
370
  return { pid: next.pid, startedAt: next.startedAt };
384
371
  },
385
- async canContinueThread(input) {
386
- return withPreparation(async () => {
387
- await ensureStarted();
388
- if (!rpc)
389
- return false;
390
- try {
391
- const existing = threads.get(input.threadId);
392
- if (existing && existing.sessionId !== input.sessionId)
393
- return false;
394
- if (existing?.turnActive)
395
- return false;
396
- const prepared = await lockedThreadConfig(input.cwd ?? '', input.modelConfigId, input.sessionId);
397
- if (existing?.needsRecreate)
398
- return false;
399
- if (existing?.loaded) {
400
- if (existing.skillsHash !== prepared.skillsHash || existing.discoveryHash !== prepared.discoveryHash) {
401
- if (!existing.hasNativeHistory)
402
- return false;
403
- await restartForSkills(input.threadId, prepared.modelConfigId);
404
- }
405
- prepared.activate();
406
- return threads.get(input.threadId)?.sessionId === input.sessionId;
407
- }
408
- const result = await rpc.request('thread/resume', { threadId: input.threadId, cwd: input.cwd,
409
- ...prepared.params }, 30_000);
410
- const resumedId = result.thread?.id ?? result.threadId;
411
- if (resumedId !== input.threadId)
412
- return false;
413
- prepared.activate();
414
- threads.set(input.threadId, { sessionId: input.sessionId, cwd: input.cwd, skillsHash: prepared.skillsHash,
415
- discoveryHash: prepared.discoveryHash, modelConfigId: prepared.modelConfigId, hasNativeHistory: true, loaded: true });
416
- return true;
417
- }
418
- catch {
419
- return false;
420
- }
421
- });
422
- },
423
372
  async readThread(input) {
424
373
  try {
425
374
  await ensureStarted();
@@ -436,17 +385,6 @@ export function createCodexAppServerAdapter(options) {
436
385
  return undefined;
437
386
  }
438
387
  },
439
- exportThread(input) {
440
- return exportTranscript(transcriptHome(), input.threadId);
441
- },
442
- async captureNativeCheckpoint(input) {
443
- const thread = threads.get(input.threadId);
444
- if (!thread || thread.sessionId !== input.sessionId)
445
- return undefined;
446
- if (!thread.lastTurnId)
447
- return { threadId: input.threadId };
448
- return { threadId: input.threadId, nativeDurableTurnId: thread.lastTurnId };
449
- },
450
388
  async start() {
451
389
  await ensureStarted();
452
390
  },
@@ -470,6 +408,30 @@ export function createCodexAppServerAdapter(options) {
470
408
  return { threadId, modelConfigId: prepared.modelConfigId };
471
409
  });
472
410
  },
411
+ async resumeThread(input) {
412
+ return withPreparation(async () => {
413
+ await ensureStarted();
414
+ if (!rpc)
415
+ throw new Error('codex_not_started');
416
+ const prepared = await lockedThreadConfig(input.cwd, input.modelConfigId, input.sessionId);
417
+ let resumedId;
418
+ try {
419
+ const resumed = await rpc.request('thread/resume', {
420
+ threadId: input.threadId, cwd: input.cwd, ...prepared.params,
421
+ }, 30_000);
422
+ resumedId = resumed.thread?.id;
423
+ }
424
+ catch {
425
+ return undefined;
426
+ }
427
+ if (resumedId !== input.threadId)
428
+ return undefined;
429
+ prepared.activate();
430
+ threads.set(input.threadId, { sessionId: input.sessionId, cwd: input.cwd, skillsHash: prepared.skillsHash,
431
+ discoveryHash: prepared.discoveryHash, modelConfigId: prepared.modelConfigId, hasNativeHistory: true, loaded: true });
432
+ return { modelConfigId: prepared.modelConfigId };
433
+ });
434
+ },
473
435
  async startTurn(input) {
474
436
  return withPreparation(async () => {
475
437
  await ensureStarted();
@@ -26,6 +26,9 @@ export function createLoopbackNativeAdapter() {
26
26
  threads.set(threadId, { sessionId: input.sessionId, items: [] });
27
27
  return { threadId };
28
28
  },
29
+ async resumeThread(input) {
30
+ return threads.get(input.threadId)?.sessionId === input.sessionId ? {} : undefined;
31
+ },
29
32
  async startTurn(input) {
30
33
  const thread = threads.get(input.threadId);
31
34
  if (!thread || thread.sessionId !== input.sessionId)
@@ -1,7 +1,7 @@
1
1
  import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { existsSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
- import { workspaceRegistrationSchema, checkpointRecordSchema, operationRecordSchema, pendingSourceEventSchema, replayPinResultSchema, retainedRangeHasGap, sourceAckSchema, sourceEventKey, sourceEventReceiptSchema, terminalRecordSchema, } from '@playcraft/common/cloud-workspace/runtime';
4
+ import { workspaceRegistrationSchema, operationRecordSchema, pendingSourceEventSchema, replayPinResultSchema, retainedRangeHasGap, sourceAckSchema, sourceEventKey, sourceEventReceiptSchema, terminalRecordSchema, } from '@playcraft/common/cloud-workspace/runtime';
5
5
  import { SqliteWorkerClient } from './sqlite-client.js';
6
6
  export const RUNTIME_STATE_FILE = 'runtime-state.sqlite';
7
7
  export const LEGACY_JOURNAL_FILE = 'journal.json';
@@ -116,21 +116,6 @@ export class RuntimeJournal {
116
116
  listTerminals(workspaceId) {
117
117
  return Object.values(this.snapshot.terminals).filter((item) => !workspaceId || item.workspaceId === workspaceId);
118
118
  }
119
- getCheckpoint(checkpointId) {
120
- return this.snapshot.checkpoints[checkpointId];
121
- }
122
- fileCheckpointId() {
123
- return this.snapshot.fileCheckpointId;
124
- }
125
- consistentCheckpointId() {
126
- return this.snapshot.consistentCheckpointId;
127
- }
128
- async setFileCheckpointId(checkpointId) {
129
- await this.run('setCheckpointId', { field: 'file', id: checkpointId });
130
- }
131
- async setConsistentCheckpointId(checkpointId) {
132
- await this.run('setCheckpointId', { field: 'consistent', id: checkpointId });
133
- }
134
119
  listManagedWrites(workspaceId) {
135
120
  return Object.values(this.snapshot.managedWrites).filter((item) => !workspaceId || item.workspaceId === workspaceId);
136
121
  }
@@ -266,11 +251,6 @@ export class RuntimeJournal {
266
251
  await this.run('upsertRecord', { bucket: 'terminals', key: parsed.terminalId, body: parsed });
267
252
  return parsed;
268
253
  }
269
- async putCheckpoint(checkpoint) {
270
- const parsed = checkpointRecordSchema.parse(checkpoint);
271
- await this.run('upsertRecord', { bucket: 'checkpoints', key: parsed.checkpointId, body: parsed });
272
- return parsed;
273
- }
274
254
  async putFileRevision(path, record, workspaceId) {
275
255
  if (workspaceId) {
276
256
  await this.run('upsertRecord', { bucket: `workspace_files:${workspaceId}`, key: path, body: record });
@@ -278,10 +258,6 @@ export class RuntimeJournal {
278
258
  }
279
259
  await this.run('upsertRecord', { bucket: 'file_revisions', key: path, body: record });
280
260
  }
281
- async replaceFileRevisions(records, workspaceId) {
282
- const entries = Object.entries(records).map(([key, body]) => ({ key, body }));
283
- await this.run('replaceBucket', { bucket: workspaceId ? `workspace_files:${workspaceId}` : 'file_revisions', entries });
284
- }
285
261
  async markDestroyed() {
286
262
  await this.run('setDestroyed', {});
287
263
  }
@@ -367,7 +343,6 @@ function emptySnapshot() {
367
343
  events: {},
368
344
  sessions: {},
369
345
  terminals: {},
370
- checkpoints: {},
371
346
  fileRevisions: {},
372
347
  approvals: {},
373
348
  managedWrites: {},
@@ -12,7 +12,7 @@ import { chmodSync, mkdirSync } from 'node:fs';
12
12
  import { dirname } from 'node:path';
13
13
  import { parentPort } from 'node:worker_threads';
14
14
  import Database from 'better-sqlite3-pinned';
15
- import { hashOperationPayload, operationRecordSchema, pendingSourceEventSchema, checkpointRecordSchema, terminalRecordSchema, workspaceRegistrationSchema, transitionOperation, canTransitionTurn, } from '@playcraft/common/cloud-workspace/runtime';
15
+ import { hashOperationPayload, operationRecordSchema, pendingSourceEventSchema, terminalRecordSchema, workspaceRegistrationSchema, transitionOperation, canTransitionTurn, } from '@playcraft/common/cloud-workspace/runtime';
16
16
  const SCHEMA_VERSION = 1;
17
17
  const MIN_SQLITE = [3, 51, 3];
18
18
  const BINDING = 'better-sqlite3@13.0.3';
@@ -68,9 +68,6 @@ function dispatch(type, payload) {
68
68
  case 'setDestroyed':
69
69
  setMeta(database, 'destroyed', '1');
70
70
  return;
71
- case 'setCheckpointId':
72
- setMeta(database, body.field === 'consistent' ? 'consistent_checkpoint_id' : 'file_checkpoint_id', String(body.id));
73
- return;
74
71
  case 'noteExecutionGroup':
75
72
  setMeta(database, 'execution_group', JSON.stringify({ ...(executionGroup(database)), ...asRecord(body.group) }));
76
73
  return;
@@ -298,7 +295,6 @@ function importLegacy(database, legacy) {
298
295
  return typeof session.sessionId === 'string' && typeof session.threadId === 'string';
299
296
  });
300
297
  importBucket(database, 'terminals', asRecord(snapshot.terminals), (value) => terminalRecordSchema.safeParse(value).success);
301
- importBucket(database, 'checkpoints', asRecord(snapshot.checkpoints), (value) => checkpointRecordSchema.safeParse(value).success);
302
298
  importBucket(database, 'approvals', asRecord(snapshot.approvals), (value) => isApproval(value));
303
299
  importBucket(database, 'managed_writes', asRecord(snapshot.managedWrites), () => true);
304
300
  importBucket(database, 'file_revisions', asRecord(snapshot.fileRevisions), () => true);
@@ -307,11 +303,6 @@ function importLegacy(database, legacy) {
307
303
  for (const [workspaceId, files] of Object.entries(workspaceFiles)) {
308
304
  importBucket(database, `workspace_files:${workspaceId}`, asRecord(files), () => true);
309
305
  }
310
- if (typeof snapshot.fileCheckpointId === 'string')
311
- setMeta(database, 'file_checkpoint_id', snapshot.fileCheckpointId);
312
- if (typeof snapshot.consistentCheckpointId === 'string') {
313
- setMeta(database, 'consistent_checkpoint_id', snapshot.consistentCheckpointId);
314
- }
315
306
  setMeta(database, 'accepted_lease_fence', String(Number(snapshot.acceptedLeaseFence) || 0));
316
307
  setMeta(database, 'destroyed', snapshot.destroyed === true ? '1' : '0');
317
308
  setMeta(database, 'runtime_epoch', String(runtimeEpoch));
@@ -441,6 +432,7 @@ function bindTurn(database, body) {
441
432
  turnBlock: undefined,
442
433
  activeTurnId: String(body.turnId),
443
434
  threadId: String(body.threadId),
435
+ recoveryContextPending: undefined,
444
436
  });
445
437
  }
446
438
  const threadId = String(body.threadId);
@@ -701,13 +693,10 @@ function dump(database) {
701
693
  events: eventsObject(database),
702
694
  sessions: bucketObject(database, 'sessions'),
703
695
  terminals: bucketObject(database, 'terminals'),
704
- checkpoints: bucketObject(database, 'checkpoints'),
705
696
  fileRevisions: bucketObject(database, 'file_revisions'),
706
697
  approvals: bucketObject(database, 'approvals'),
707
698
  managedWrites: bucketObject(database, 'managed_writes'),
708
699
  workspaceDependencies: bucketObject(database, 'workspace_dependencies'),
709
- fileCheckpointId: metaString(database, 'file_checkpoint_id') || undefined,
710
- consistentCheckpointId: metaString(database, 'consistent_checkpoint_id') || undefined,
711
700
  executionGroup: executionGroup(database),
712
701
  runtimeEpoch: metaNumber(database, 'runtime_epoch'),
713
702
  lastSourceSequence: currentCounter(database),