@pstdio/pocketcoder-cli 0.7.2 → 0.7.3
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/index.js +82 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5214,7 +5214,7 @@ function isYargsInstance(y) {
|
|
|
5214
5214
|
var Yargs = YargsFactory(esm_default);
|
|
5215
5215
|
var yargs_default = Yargs;
|
|
5216
5216
|
// package.json
|
|
5217
|
-
var version = "0.7.
|
|
5217
|
+
var version = "0.7.3";
|
|
5218
5218
|
|
|
5219
5219
|
// src/command/cli-context.ts
|
|
5220
5220
|
import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
@@ -21248,6 +21248,17 @@ function sqlValues(values) {
|
|
|
21248
21248
|
}
|
|
21249
21249
|
var timestamptz = (name2) => timestamp2(name2, { withTimezone: true, mode: "date" });
|
|
21250
21250
|
|
|
21251
|
+
// ../db/src/schema/structured-json.ts
|
|
21252
|
+
var structuredJson = customType2({
|
|
21253
|
+
dataType: () => "jsonb",
|
|
21254
|
+
codec: "jsonb",
|
|
21255
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value
|
|
21256
|
+
});
|
|
21257
|
+
function structuredJsonValue(column) {
|
|
21258
|
+
return sql`CASE WHEN jsonb_typeof(${column}) = 'string'
|
|
21259
|
+
THEN (${column} #>> '{}')::jsonb ELSE ${column} END`;
|
|
21260
|
+
}
|
|
21261
|
+
|
|
21251
21262
|
// ../db/src/schema/access.ts
|
|
21252
21263
|
function createAccessTables(table2 = pgTable) {
|
|
21253
21264
|
const templates2 = table2("templates", {
|
|
@@ -21256,7 +21267,7 @@ function createAccessTables(table2 = pgTable) {
|
|
|
21256
21267
|
version: text2("version").notNull(),
|
|
21257
21268
|
digest: text2("digest").notNull().unique(),
|
|
21258
21269
|
description: text2("description"),
|
|
21259
|
-
spec:
|
|
21270
|
+
spec: structuredJson("spec").$type().notNull(),
|
|
21260
21271
|
status: text2("status").$type().notNull(),
|
|
21261
21272
|
createdAt: timestamptz("created_at").notNull(),
|
|
21262
21273
|
retiredAt: timestamptz("retired_at")
|
|
@@ -37314,7 +37325,7 @@ function createActivityTables(table2 = pgTable, { workspaces: workspaces2 }) {
|
|
|
37314
37325
|
role: text2("role").$type().notNull(),
|
|
37315
37326
|
content: text2("content").notNull(),
|
|
37316
37327
|
occurredAt: timestamptz("occurred_at").notNull(),
|
|
37317
|
-
metadata:
|
|
37328
|
+
metadata: structuredJson("metadata").$type().notNull().default({}),
|
|
37318
37329
|
createdAt: timestamptz("created_at").notNull()
|
|
37319
37330
|
}, (table3) => [
|
|
37320
37331
|
primaryKey({ columns: [table3.workspaceId, table3.seq] }),
|
|
@@ -37368,9 +37379,9 @@ function createPersistenceTables(table2 = pgTable, { principals }, { workspaces:
|
|
|
37368
37379
|
workspaceId: uuid("workspace_id").notNull().references(() => workspaces2.id),
|
|
37369
37380
|
principalId: uuid("principal_id").notNull().references(() => principals.id),
|
|
37370
37381
|
providerKind: text2("provider_kind").notNull(),
|
|
37371
|
-
providerRef:
|
|
37382
|
+
providerRef: structuredJson("provider_ref").$type().notNull(),
|
|
37372
37383
|
state: text2("state").$type().notNull(),
|
|
37373
|
-
mountManifest:
|
|
37384
|
+
mountManifest: structuredJson("mount_manifest").$type().notNull(),
|
|
37374
37385
|
logicalBytes: bigint2("logical_bytes", { mode: "number" }),
|
|
37375
37386
|
fileCount: bigint2("file_count", { mode: "number" }),
|
|
37376
37387
|
retainedUntil: timestamptz("retained_until"),
|
|
@@ -37393,11 +37404,11 @@ function createPersistenceTables(table2 = pgTable, { principals }, { workspaces:
|
|
|
37393
37404
|
state: text2("state").$type().notNull(),
|
|
37394
37405
|
reasonCode: text2("reason_code").$type(),
|
|
37395
37406
|
providerKind: text2("provider_kind").notNull(),
|
|
37396
|
-
providerRef:
|
|
37397
|
-
templateSnapshot:
|
|
37407
|
+
providerRef: structuredJson("provider_ref").$type(),
|
|
37408
|
+
templateSnapshot: structuredJson("template_snapshot").$type().notNull(),
|
|
37398
37409
|
templateDigest: text2("template_digest").notNull(),
|
|
37399
|
-
sourceProvenance:
|
|
37400
|
-
manifest:
|
|
37410
|
+
sourceProvenance: structuredJson("source_provenance").$type(),
|
|
37411
|
+
manifest: structuredJson("manifest").$type(),
|
|
37401
37412
|
manifestDigest: text2("manifest_digest"),
|
|
37402
37413
|
logicalBytes: bigint2("logical_bytes", { mode: "number" }),
|
|
37403
37414
|
storedBytes: bigint2("stored_bytes", { mode: "number" }),
|
|
@@ -37452,7 +37463,7 @@ function createWorkspaceTables(table2 = pgTable, { principals, machineKeys, temp
|
|
|
37452
37463
|
templateName: text2("template_name").notNull(),
|
|
37453
37464
|
templateVersion: text2("template_version").notNull(),
|
|
37454
37465
|
templateDigest: text2("template_digest").notNull(),
|
|
37455
|
-
templateSnapshot:
|
|
37466
|
+
templateSnapshot: structuredJson("template_snapshot").$type().notNull(),
|
|
37456
37467
|
state: text2("state").$type().notNull(),
|
|
37457
37468
|
reasonCode: text2("reason_code").$type(),
|
|
37458
37469
|
agentState: text2("agent_state").$type().notNull().default("unknown"),
|
|
@@ -37463,9 +37474,9 @@ function createWorkspaceTables(table2 = pgTable, { principals, machineKeys, temp
|
|
|
37463
37474
|
failureLogTailTruncated: boolean2("failure_log_tail_truncated").notNull().default(false),
|
|
37464
37475
|
failureLastLogSeq: bigint2("failure_last_log_seq", { mode: "number" }),
|
|
37465
37476
|
terminalIntent: text2("terminal_intent").$type(),
|
|
37466
|
-
launchInput:
|
|
37477
|
+
launchInput: structuredJson("launch_input").$type(),
|
|
37467
37478
|
providerKind: text2("provider_kind"),
|
|
37468
|
-
providerRef:
|
|
37479
|
+
providerRef: structuredJson("provider_ref").$type(),
|
|
37469
37480
|
provisioningMode: text2("provisioning_mode").$type(),
|
|
37470
37481
|
registrationDigest: bytea2("registration_digest").$type(),
|
|
37471
37482
|
registrationExpiresAt: timestamptz("registration_expires_at"),
|
|
@@ -37476,20 +37487,20 @@ function createWorkspaceTables(table2 = pgTable, { principals, machineKeys, temp
|
|
|
37476
37487
|
readyAt: timestamptz("ready_at"),
|
|
37477
37488
|
lastActivityAt: timestamptz("last_activity_at"),
|
|
37478
37489
|
launchAttempts: integer("launch_attempts").notNull().default(0),
|
|
37479
|
-
health:
|
|
37480
|
-
metadata:
|
|
37490
|
+
health: structuredJson("health").$type().notNull().default({}),
|
|
37491
|
+
metadata: structuredJson("metadata").$type().notNull().default({}),
|
|
37481
37492
|
deadlineAt: timestamptz("deadline_at").notNull(),
|
|
37482
37493
|
createdAt: timestamptz("created_at").notNull(),
|
|
37483
37494
|
updatedAt: timestamptz("updated_at").notNull(),
|
|
37484
37495
|
terminalAt: timestamptz("terminal_at"),
|
|
37485
37496
|
originWorkspaceId: uuid("origin_workspace_id"),
|
|
37486
37497
|
restoredFromCheckpointId: uuid("restored_from_checkpoint_id"),
|
|
37487
|
-
sourceDescriptor:
|
|
37488
|
-
resolvedSource:
|
|
37498
|
+
sourceDescriptor: structuredJson("source_descriptor").$type(),
|
|
37499
|
+
resolvedSource: structuredJson("resolved_source").$type(),
|
|
37489
37500
|
persistenceCapability: text2("persistence_capability").$type().notNull().default("filesystem_only"),
|
|
37490
37501
|
latestCheckpointId: uuid("latest_checkpoint_id"),
|
|
37491
37502
|
launchMode: text2("launch_mode").$type().notNull().default("create"),
|
|
37492
|
-
outputs:
|
|
37503
|
+
outputs: structuredJson("outputs").$type().notNull().default({})
|
|
37493
37504
|
}, (table3) => [
|
|
37494
37505
|
check("workspaces_state_check", sql`${table3.state} IN ${sqlValues(WORKSPACE_STATES)}`),
|
|
37495
37506
|
check("workspaces_reason_code_check", sql`${table3.reasonCode} IS NULL OR ${table3.reasonCode} IN ${sqlValues(REASON_CODES)}`),
|
|
@@ -37552,7 +37563,7 @@ function createWorkspaceTables(table2 = pgTable, { principals, machineKeys, temp
|
|
|
37552
37563
|
driverKind: text2("driver_kind").notNull(),
|
|
37553
37564
|
eligibilityFingerprint: text2("eligibility_fingerprint").notNull(),
|
|
37554
37565
|
state: text2("state").$type().notNull(),
|
|
37555
|
-
providerRef:
|
|
37566
|
+
providerRef: structuredJson("provider_ref").$type(),
|
|
37556
37567
|
enrollmentDigest: bytea2("enrollment_digest").$type(),
|
|
37557
37568
|
enrollmentExpiresAt: timestamptz("enrollment_expires_at"),
|
|
37558
37569
|
workspaceId: uuid("workspace_id").references(() => workspaces2.id),
|
|
@@ -37944,7 +37955,7 @@ function createOutputs({ db, tables: { workspaceOutputs: outputs2, workspaces: w
|
|
|
37944
37955
|
const row = { ...input, seq: requiredRow(latest).seq + 1 };
|
|
37945
37956
|
await tx.insert(outputs2).values({ ...row, value: row.value === null ? sql`'null'::jsonb` : row.value });
|
|
37946
37957
|
await tx.update(workspaces3).set({
|
|
37947
|
-
outputs: sql`${workspaces3.outputs} || jsonb_build_object(${input.name}::text, ${sql.param(input.value, outputs2.value)}::jsonb)`,
|
|
37958
|
+
outputs: sql`${structuredJsonValue(workspaces3.outputs)} || jsonb_build_object(${input.name}::text, ${sql.param(input.value, outputs2.value)}::jsonb)`,
|
|
37948
37959
|
updatedAt: input.occurredAt
|
|
37949
37960
|
}).where(eq(workspaces3.id, input.workspaceId));
|
|
37950
37961
|
return row;
|
|
@@ -39664,7 +39675,7 @@ function createWorkspaces(context) {
|
|
|
39664
39675
|
const cursor = db.select({ createdAt: workspaces3.createdAt, id: workspaces3.id }).from(workspaces3).where(and(eq(workspaces3.id, filter.cursor), eq(workspaces3.principalId, principalId)));
|
|
39665
39676
|
cursorFilter = sql`(${workspaces3.createdAt}, ${workspaces3.id}) < (${cursor})`;
|
|
39666
39677
|
}
|
|
39667
|
-
const rows = await db.select().from(workspaces3).where(and(eq(workspaces3.principalId, principalId), filter.externalId ? eq(workspaces3.externalId, filter.externalId) : undefined, filter.state ? eq(workspaces3.state, filter.state) : undefined, filter.template ? eq(workspaces3.templateName, filter.template) : undefined, filter.metadata ? sql`${workspaces3.metadata} @> ${sql.param(filter.metadata, workspaces3.metadata)}::jsonb` : undefined, filter.createdAfter ? gte(workspaces3.createdAt, filter.createdAfter) : undefined, filter.createdBefore ? lt(workspaces3.createdAt, filter.createdBefore) : undefined, cursorFilter)).orderBy(desc2(workspaces3.createdAt), desc2(workspaces3.id)).limit(filter.limit);
|
|
39678
|
+
const rows = await db.select().from(workspaces3).where(and(eq(workspaces3.principalId, principalId), filter.externalId ? eq(workspaces3.externalId, filter.externalId) : undefined, filter.state ? eq(workspaces3.state, filter.state) : undefined, filter.template ? eq(workspaces3.templateName, filter.template) : undefined, filter.metadata ? sql`${structuredJsonValue(workspaces3.metadata)} @> ${sql.param(filter.metadata, workspaces3.metadata)}::jsonb` : undefined, filter.createdAfter ? gte(workspaces3.createdAt, filter.createdAfter) : undefined, filter.createdBefore ? lt(workspaces3.createdAt, filter.createdBefore) : undefined, cursorFilter)).orderBy(desc2(workspaces3.createdAt), desc2(workspaces3.id)).limit(filter.limit);
|
|
39668
39679
|
return rows.map(workspaceFromRow);
|
|
39669
39680
|
}
|
|
39670
39681
|
};
|
|
@@ -41480,6 +41491,43 @@ class PersistenceCheckpointService {
|
|
|
41480
41491
|
|
|
41481
41492
|
// ../server/src/persistence/persistence-maintenance.ts
|
|
41482
41493
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
41494
|
+
|
|
41495
|
+
// ../server/src/persistence/persistence-cleanup.ts
|
|
41496
|
+
async function cleanupPreservedStorage(context, storageId) {
|
|
41497
|
+
const { store, driver } = context.deps;
|
|
41498
|
+
const storage = await store.getStorage(storageId);
|
|
41499
|
+
if (storage?.state !== "retained")
|
|
41500
|
+
return;
|
|
41501
|
+
if (storage.lastErrorCode && storage.lastErrorCode !== "storage_cleanup_failed")
|
|
41502
|
+
return;
|
|
41503
|
+
const workspace = await store.getWorkspace(storage.workspaceId);
|
|
41504
|
+
if (workspace?.state !== "preserved" || !workspace.terminalAt)
|
|
41505
|
+
return;
|
|
41506
|
+
const checkpoints = (await store.listCheckpoints(storage.principalId)).filter((checkpoint) => checkpoint.storageId === storage.id);
|
|
41507
|
+
if (checkpoints.length === 0 || checkpoints.some((checkpoint) => checkpoint.state !== "deleted"))
|
|
41508
|
+
return;
|
|
41509
|
+
const checkpointIds = new Set(checkpoints.map((checkpoint) => checkpoint.id));
|
|
41510
|
+
const operations = await store.listIncompleteOperations();
|
|
41511
|
+
if (operations.some((operation) => operation.workspaceId === workspace.id || operation.resultWorkspaceId === workspace.id || operation.checkpointId !== null && checkpointIds.has(operation.checkpointId)))
|
|
41512
|
+
return;
|
|
41513
|
+
try {
|
|
41514
|
+
if ((await driver.list()).some((provider) => provider.workspaceId === workspace.id))
|
|
41515
|
+
return;
|
|
41516
|
+
await context.storageDriver().deleteStorage(storage.providerRef);
|
|
41517
|
+
const now = context.now();
|
|
41518
|
+
await store.updateWorkspaceStorage(storage.id, {
|
|
41519
|
+
state: "deleted",
|
|
41520
|
+
deletedAt: now,
|
|
41521
|
+
retainedUntil: null,
|
|
41522
|
+
lastErrorCode: null
|
|
41523
|
+
}, now);
|
|
41524
|
+
} catch (error51) {
|
|
41525
|
+
await store.updateWorkspaceStorage(storage.id, { lastErrorCode: "storage_cleanup_failed" }, context.now());
|
|
41526
|
+
context.deps.log?.(`storage cleanup ${storage.id}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
41527
|
+
}
|
|
41528
|
+
}
|
|
41529
|
+
|
|
41530
|
+
// ../server/src/persistence/persistence-maintenance.ts
|
|
41483
41531
|
class PersistenceMaintenanceService {
|
|
41484
41532
|
context;
|
|
41485
41533
|
constructor(context) {
|
|
@@ -41531,6 +41579,10 @@ class PersistenceMaintenanceService {
|
|
|
41531
41579
|
this.context.deps.log?.(`retention ${checkpoint.id}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
41532
41580
|
}
|
|
41533
41581
|
}
|
|
41582
|
+
const deletedCheckpoints = await this.context.deps.store.listCheckpoints(principal.id, { state: "deleted" });
|
|
41583
|
+
for (const storageId of new Set(deletedCheckpoints.map((checkpoint) => checkpoint.storageId))) {
|
|
41584
|
+
await cleanupPreservedStorage(this.context, storageId);
|
|
41585
|
+
}
|
|
41534
41586
|
}
|
|
41535
41587
|
return { deleted, skipped, transcriptsDeleted };
|
|
41536
41588
|
}
|
|
@@ -41557,8 +41609,14 @@ class PersistenceMaintenanceService {
|
|
|
41557
41609
|
async delete(principal, checkpointId, idempotencyKey) {
|
|
41558
41610
|
const requestDigest = digestOf({ checkpoint_id: checkpointId });
|
|
41559
41611
|
const replay = await this.context.replayedOperation(principal.id, "delete", idempotencyKey, requestDigest, "Changed delete request.");
|
|
41560
|
-
if (replay)
|
|
41612
|
+
if (replay) {
|
|
41613
|
+
if (replay.state === "succeeded") {
|
|
41614
|
+
const checkpoint2 = await this.context.deps.store.getCheckpoint(checkpointId);
|
|
41615
|
+
if (checkpoint2)
|
|
41616
|
+
await cleanupPreservedStorage(this.context, checkpoint2.storageId);
|
|
41617
|
+
}
|
|
41561
41618
|
return replay;
|
|
41619
|
+
}
|
|
41562
41620
|
const checkpoint = await this.context.getCheckpointOwned(principal, checkpointId);
|
|
41563
41621
|
const activeRestore = (await this.context.deps.store.listIncompleteOperations()).some((operation) => operation.kind === "restore" && operation.checkpointId === checkpoint.id);
|
|
41564
41622
|
if (activeRestore) {
|
|
@@ -41602,6 +41660,7 @@ class PersistenceMaintenanceService {
|
|
|
41602
41660
|
} catch {
|
|
41603
41661
|
await this.context.failOperation(inserted.operation.id, "checkpoint_failed");
|
|
41604
41662
|
}
|
|
41663
|
+
await cleanupPreservedStorage(this.context, checkpoint.storageId);
|
|
41605
41664
|
return await this.context.deps.store.getOperation(inserted.operation.id) ?? inserted.operation;
|
|
41606
41665
|
}
|
|
41607
41666
|
}
|
|
@@ -52024,8 +52083,7 @@ async function startPocketCoderServer(config2 = loadConfig(), options = {}) {
|
|
|
52024
52083
|
const url2 = `http://${healthHost}:${server.port}`;
|
|
52025
52084
|
log(`listening on http://${config2.listenHost}:${server.port}`);
|
|
52026
52085
|
log(`workspaces reach this server at ${config2.workspaceServerUrl}`);
|
|
52027
|
-
|
|
52028
|
-
warmPool.reconcile().catch((error51) => log(`warm pool initial reconcile failed: ${String(error51)}`));
|
|
52086
|
+
const initialWarmPool = warmPool?.reconcile().catch((error51) => log(`warm pool initial reconcile failed: ${String(error51)}`));
|
|
52029
52087
|
let stopPromise = null;
|
|
52030
52088
|
return {
|
|
52031
52089
|
config: config2,
|
|
@@ -52041,6 +52099,7 @@ async function startPocketCoderServer(config2 = loadConfig(), options = {}) {
|
|
|
52041
52099
|
if (warmPoolTimer)
|
|
52042
52100
|
clearInterval(warmPoolTimer);
|
|
52043
52101
|
await server.stop(true);
|
|
52102
|
+
await initialWarmPool;
|
|
52044
52103
|
await store.close();
|
|
52045
52104
|
})();
|
|
52046
52105
|
return stopPromise;
|