@p4code/cli 0.2.29 → 0.2.31
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/bin.mjs +245 -62
- package/dist/client/assets/{DiffPanel-B7xS8NZM.js → DiffPanel-B-2-QUPV.js} +3 -3
- package/dist/client/assets/{FilePreviewPanel-bSnXkh8d.js → FilePreviewPanel-C4YhaSrH.js} +4 -4
- package/dist/client/assets/{PreviewPanel-D3VE3CQQ.js → PreviewPanel-ZUpYbtlk.js} +2 -2
- package/dist/client/assets/{PullRequestCodeTab-CCDZAkXW.js → PullRequestCodeTab-7Mw21G70.js} +2 -2
- package/dist/client/assets/arrow-right-BPchBceB.js +2 -0
- package/dist/client/assets/{fileCommentAnnotations-WnWcXMH1.js → fileCommentAnnotations-B9hOUK3h.js} +2 -2
- package/dist/client/assets/{index-CPzWH77f.js → index-BOEKM5ad.js} +217 -207
- package/dist/client/assets/index-CfY-70_w.css +1 -0
- package/dist/client/assets/previewAssetResource-B_r-a_Fy.js +48 -0
- package/dist/client/assets/{renderFileChildren-xN40UqRe.js → renderFileChildren-DvgAC6eg.js} +2 -2
- package/dist/client/assets/{toggle-group-CVd1E9dE.js → toggle-group-BKq4vMCI.js} +2 -2
- package/dist/client/index.html +3 -3
- package/package.json +1 -1
- package/dist/client/assets/arrow-right-4WRbFrGp.js +0 -2
- package/dist/client/assets/index-BOMxG-b0.css +0 -1
- package/dist/client/assets/previewAssetResource-DG52hZXj.js +0 -48
package/dist/bin.mjs
CHANGED
|
@@ -238,7 +238,7 @@ const make$90 = () => {
|
|
|
238
238
|
const layer$81 = Layer.sync(NetService, make$90);
|
|
239
239
|
//#endregion
|
|
240
240
|
//#region package.json
|
|
241
|
-
var version = "0.2.
|
|
241
|
+
var version = "0.2.31";
|
|
242
242
|
//#endregion
|
|
243
243
|
//#region src/config.ts
|
|
244
244
|
/**
|
|
@@ -7343,6 +7343,7 @@ const STATIC_KEYBINDING_COMMANDS = [
|
|
|
7343
7343
|
"terminal.close",
|
|
7344
7344
|
"rightPanel.toggle",
|
|
7345
7345
|
"board.toggle",
|
|
7346
|
+
"todos.toggle",
|
|
7346
7347
|
"diff.toggle",
|
|
7347
7348
|
"preview.toggle",
|
|
7348
7349
|
"preview.refresh",
|
|
@@ -7646,6 +7647,12 @@ const Task = Schema$1.Struct({
|
|
|
7646
7647
|
priority: TaskPriority,
|
|
7647
7648
|
assignee: Schema$1.NullOr(TrimmedNonEmptyString.check(Schema$1.isMaxLength(TASK_ASSIGNEE_MAX_LENGTH))),
|
|
7648
7649
|
labels: Schema$1.Array(TaskLabel).check(Schema$1.isMaxLength(TASK_LABELS_MAX_COUNT)),
|
|
7650
|
+
/**
|
|
7651
|
+
* When `status` last changed. Nullable-with-default for rows written by an
|
|
7652
|
+
* older server; current stores always stamp it. A dedicated timestamp keeps
|
|
7653
|
+
* completion and archive dates stable when title or labels change later.
|
|
7654
|
+
*/
|
|
7655
|
+
statusChangedAt: Schema$1.NullOr(IsoDateTime).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
7649
7656
|
createdAt: IsoDateTime,
|
|
7650
7657
|
updatedAt: IsoDateTime
|
|
7651
7658
|
});
|
|
@@ -7712,6 +7719,7 @@ const HubTaskPutInput = Schema$1.Struct({
|
|
|
7712
7719
|
labels: LabelsField,
|
|
7713
7720
|
orderKey: Schema$1.NullOr(OrderKeyField),
|
|
7714
7721
|
createdAt: IsoDateTime,
|
|
7722
|
+
statusChangedAt: Schema$1.optional(IsoDateTime),
|
|
7715
7723
|
readableIdPrefix: Schema$1.optional(TrimmedNonEmptyString)
|
|
7716
7724
|
});
|
|
7717
7725
|
/**
|
|
@@ -8238,9 +8246,8 @@ const ServerSettings = Schema$1.Struct({
|
|
|
8238
8246
|
model: DEFAULT_TEXT_GENERATION_MODEL
|
|
8239
8247
|
}))),
|
|
8240
8248
|
/**
|
|
8241
|
-
*
|
|
8242
|
-
*
|
|
8243
|
-
* the next thread instead of resetting to none each time.
|
|
8249
|
+
* Recommended supervisor model used when opening the Fusion picker. This
|
|
8250
|
+
* does not activate Fusion for a draft by itself.
|
|
8244
8251
|
*/
|
|
8245
8252
|
fusionWatcherModelSelection: Schema$1.NullOr(ModelSelection).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
8246
8253
|
sourceControlWritingStyle: SourceControlWritingStyleSettings.pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
|
|
@@ -8484,7 +8491,9 @@ const ServerProviderSkill = Schema$1.Struct({
|
|
|
8484
8491
|
scope: Schema$1.optional(TrimmedNonEmptyString),
|
|
8485
8492
|
enabled: Schema$1.Boolean,
|
|
8486
8493
|
displayName: Schema$1.optional(TrimmedNonEmptyString),
|
|
8487
|
-
shortDescription: Schema$1.optional(TrimmedNonEmptyString)
|
|
8494
|
+
shortDescription: Schema$1.optional(TrimmedNonEmptyString),
|
|
8495
|
+
/** Interaction mode P4Code selects when the user inserts this skill. */
|
|
8496
|
+
requiredInteractionMode: Schema$1.optional(ProviderInteractionMode)
|
|
8488
8497
|
});
|
|
8489
8498
|
/**
|
|
8490
8499
|
* Availability of a configured provider instance from the runtime's POV.
|
|
@@ -15575,6 +15584,14 @@ var _048_ProjectionThreadsPinned_default = Effect.gen(function* () {
|
|
|
15575
15584
|
`;
|
|
15576
15585
|
});
|
|
15577
15586
|
//#endregion
|
|
15587
|
+
//#region src/persistence/Migrations/049_TaskStatusChangedAt.ts
|
|
15588
|
+
/** Preserve status transition time independently from ordinary task edits. */
|
|
15589
|
+
var _049_TaskStatusChangedAt_default = Effect.gen(function* () {
|
|
15590
|
+
const sql = yield* SqlClient.SqlClient;
|
|
15591
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN status_changed_at TEXT`;
|
|
15592
|
+
yield* sql`UPDATE tasks SET status_changed_at = updated_at WHERE status_changed_at IS NULL`;
|
|
15593
|
+
});
|
|
15594
|
+
//#endregion
|
|
15578
15595
|
//#region src/persistence/Migrations.ts
|
|
15579
15596
|
/**
|
|
15580
15597
|
* MigrationsLive - Migration runner with inline loader
|
|
@@ -15835,6 +15852,11 @@ const migrationEntries = [
|
|
|
15835
15852
|
48,
|
|
15836
15853
|
"ProjectionThreadsPinned",
|
|
15837
15854
|
_048_ProjectionThreadsPinned_default
|
|
15855
|
+
],
|
|
15856
|
+
[
|
|
15857
|
+
49,
|
|
15858
|
+
"TaskStatusChangedAt",
|
|
15859
|
+
_049_TaskStatusChangedAt_default
|
|
15838
15860
|
]
|
|
15839
15861
|
];
|
|
15840
15862
|
const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -18472,6 +18494,7 @@ const TASK_COLUMNS$1 = `
|
|
|
18472
18494
|
assignee,
|
|
18473
18495
|
labels_json AS "labels",
|
|
18474
18496
|
order_key AS "orderKey",
|
|
18497
|
+
status_changed_at AS "statusChangedAt",
|
|
18475
18498
|
created_at AS "createdAt",
|
|
18476
18499
|
updated_at AS "updatedAt"
|
|
18477
18500
|
`;
|
|
@@ -18496,6 +18519,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
18496
18519
|
assignee,
|
|
18497
18520
|
labels_json,
|
|
18498
18521
|
order_key,
|
|
18522
|
+
status_changed_at,
|
|
18499
18523
|
created_at,
|
|
18500
18524
|
updated_at
|
|
18501
18525
|
)
|
|
@@ -18513,6 +18537,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
18513
18537
|
${row.assignee},
|
|
18514
18538
|
${JSON.stringify(row.labels)},
|
|
18515
18539
|
${row.orderKey},
|
|
18540
|
+
${row.statusChangedAt},
|
|
18516
18541
|
${row.createdAt},
|
|
18517
18542
|
${row.updatedAt}
|
|
18518
18543
|
)
|
|
@@ -18530,6 +18555,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
18530
18555
|
assignee = excluded.assignee,
|
|
18531
18556
|
labels_json = excluded.labels_json,
|
|
18532
18557
|
order_key = excluded.order_key,
|
|
18558
|
+
status_changed_at = excluded.status_changed_at,
|
|
18533
18559
|
created_at = excluded.created_at,
|
|
18534
18560
|
updated_at = excluded.updated_at
|
|
18535
18561
|
`
|
|
@@ -18629,6 +18655,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
18629
18655
|
...input.assignee !== void 0 ? { assignee: input.assignee } : {},
|
|
18630
18656
|
...input.labels !== void 0 ? { labels: input.labels } : {},
|
|
18631
18657
|
...input.orderKey !== void 0 ? { orderKey: input.orderKey } : {},
|
|
18658
|
+
statusChangedAt: input.status !== void 0 && input.status !== existing.value.status ? updatedAt : existing.value.statusChangedAt,
|
|
18632
18659
|
updatedAt
|
|
18633
18660
|
};
|
|
18634
18661
|
yield* upsertTaskRow(updated);
|
|
@@ -18668,6 +18695,7 @@ const makeTaskRepository = Effect.gen(function* () {
|
|
|
18668
18695
|
...input.patch.assignee !== void 0 ? { assignee: input.patch.assignee } : {},
|
|
18669
18696
|
...input.patch.labels !== void 0 ? { labels: input.patch.labels } : {},
|
|
18670
18697
|
...input.patch.orderKey !== void 0 ? { orderKey: input.patch.orderKey } : {},
|
|
18698
|
+
statusChangedAt: input.patch.status !== void 0 && input.patch.status !== existing.value.status ? updatedAt : existing.value.statusChangedAt,
|
|
18671
18699
|
updatedAt
|
|
18672
18700
|
};
|
|
18673
18701
|
yield* upsertTaskRow(updated);
|
|
@@ -18803,6 +18831,7 @@ const createTaskRoute = HttpRouter.add("POST", "/tasks", respondToHubFailures(Ef
|
|
|
18803
18831
|
assignee: input.assignee ?? null,
|
|
18804
18832
|
labels: input.labels ?? [],
|
|
18805
18833
|
orderKey: input.orderKey ?? null,
|
|
18834
|
+
statusChangedAt: timestamp,
|
|
18806
18835
|
createdAt: timestamp,
|
|
18807
18836
|
updatedAt: timestamp
|
|
18808
18837
|
};
|
|
@@ -18843,7 +18872,8 @@ const putTaskRoute = HttpRouter.add("PUT", "/tasks/:taskId", respondToHubFailure
|
|
|
18843
18872
|
priority: input.priority,
|
|
18844
18873
|
assignee: input.assignee,
|
|
18845
18874
|
labels: input.labels,
|
|
18846
|
-
orderKey: input.orderKey
|
|
18875
|
+
orderKey: input.orderKey,
|
|
18876
|
+
statusChangedAt: input.statusChangedAt ?? input.createdAt
|
|
18847
18877
|
};
|
|
18848
18878
|
const existing = yield* tasks.getById({ taskId });
|
|
18849
18879
|
if (Option.isNone(existing)) {
|
|
@@ -18858,6 +18888,7 @@ const putTaskRoute = HttpRouter.add("PUT", "/tasks/:taskId", respondToHubFailure
|
|
|
18858
18888
|
const replaced = {
|
|
18859
18889
|
...existing.value,
|
|
18860
18890
|
...fields,
|
|
18891
|
+
statusChangedAt: input.statusChangedAt ?? (input.status !== existing.value.status ? timestamp : existing.value.statusChangedAt ?? existing.value.updatedAt),
|
|
18861
18892
|
updatedAt: timestamp
|
|
18862
18893
|
};
|
|
18863
18894
|
yield* tasks.upsert(replaced);
|
|
@@ -19547,6 +19578,14 @@ var _013_FeedArticleCategories_default = Effect.gen(function* () {
|
|
|
19547
19578
|
yield* (yield* SqlClient.SqlClient)`ALTER TABLE feed_articles ADD COLUMN category TEXT`;
|
|
19548
19579
|
});
|
|
19549
19580
|
//#endregion
|
|
19581
|
+
//#region src/hub/Migrations/014_TaskStatusChangedAt.ts
|
|
19582
|
+
/** Keep completion and archive time stable across server replicas. */
|
|
19583
|
+
var _014_TaskStatusChangedAt_default = Effect.gen(function* () {
|
|
19584
|
+
const sql = yield* SqlClient.SqlClient;
|
|
19585
|
+
yield* sql`ALTER TABLE tasks ADD COLUMN status_changed_at TEXT`;
|
|
19586
|
+
yield* sql`UPDATE tasks SET status_changed_at = updated_at WHERE status_changed_at IS NULL`;
|
|
19587
|
+
});
|
|
19588
|
+
//#endregion
|
|
19550
19589
|
//#region src/hub/Migrations.ts
|
|
19551
19590
|
/**
|
|
19552
19591
|
* Hub migrations.
|
|
@@ -19622,6 +19661,11 @@ const hubMigrationEntries = [
|
|
|
19622
19661
|
13,
|
|
19623
19662
|
"FeedArticleCategories",
|
|
19624
19663
|
_013_FeedArticleCategories_default
|
|
19664
|
+
],
|
|
19665
|
+
[
|
|
19666
|
+
14,
|
|
19667
|
+
"TaskStatusChangedAt",
|
|
19668
|
+
_014_TaskStatusChangedAt_default
|
|
19625
19669
|
]
|
|
19626
19670
|
];
|
|
19627
19671
|
const hubMigrationLoader = Migrator.fromRecord(Object.fromEntries(hubMigrationEntries.map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -20217,11 +20261,13 @@ function parseMarkdownFrontmatter(contents) {
|
|
|
20217
20261
|
const name = typeof record.name === "string" ? record.name.trim() : "";
|
|
20218
20262
|
const description = typeof record.description === "string" ? record.description.trim() : "";
|
|
20219
20263
|
const disableModelInvocation = readFrontmatterBoolean(record["disable-model-invocation"]);
|
|
20264
|
+
const requiredInteractionMode = record["required-interaction-mode"] === "default" || record["required-interaction-mode"] === "plan" ? record["required-interaction-mode"] : void 0;
|
|
20220
20265
|
return {
|
|
20221
20266
|
kind: "parsed",
|
|
20222
20267
|
...name ? { name } : {},
|
|
20223
20268
|
...description ? { description } : {},
|
|
20224
|
-
...disableModelInvocation === void 0 ? {} : { disableModelInvocation }
|
|
20269
|
+
...disableModelInvocation === void 0 ? {} : { disableModelInvocation },
|
|
20270
|
+
...requiredInteractionMode === void 0 ? {} : { requiredInteractionMode }
|
|
20225
20271
|
};
|
|
20226
20272
|
}
|
|
20227
20273
|
/**
|
|
@@ -20305,7 +20351,8 @@ const discoverClaudeSkills = Effect.fn("discoverClaudeSkills")(function* (config
|
|
|
20305
20351
|
path: skillPath
|
|
20306
20352
|
}, disabledSkills ?? []),
|
|
20307
20353
|
scope: root.scope,
|
|
20308
|
-
...frontmatter.kind === "parsed" && frontmatter.description ? { description: frontmatter.description } : {}
|
|
20354
|
+
...frontmatter.kind === "parsed" && frontmatter.description ? { description: frontmatter.description } : {},
|
|
20355
|
+
...frontmatter.kind === "parsed" && frontmatter.requiredInteractionMode ? { requiredInteractionMode: frontmatter.requiredInteractionMode } : {}
|
|
20309
20356
|
});
|
|
20310
20357
|
}
|
|
20311
20358
|
}
|
|
@@ -24035,6 +24082,7 @@ const ReadFromSequenceRequestSchema = Schema$1.Struct({
|
|
|
24035
24082
|
sequenceExclusive: NonNegativeInt,
|
|
24036
24083
|
limit: Schema$1.Number
|
|
24037
24084
|
});
|
|
24085
|
+
const ReadByCommandIdRequestSchema = Schema$1.Struct({ commandId: CommandId });
|
|
24038
24086
|
const DEFAULT_READ_FROM_SEQUENCE_LIMIT = 1e3;
|
|
24039
24087
|
const READ_PAGE_SIZE = 500;
|
|
24040
24088
|
function inferActorKind(event) {
|
|
@@ -24125,6 +24173,27 @@ const makeEventStore = Effect.gen(function* () {
|
|
|
24125
24173
|
WHERE sequence > ${request.sequenceExclusive}
|
|
24126
24174
|
ORDER BY sequence ASC
|
|
24127
24175
|
LIMIT ${request.limit}
|
|
24176
|
+
`
|
|
24177
|
+
});
|
|
24178
|
+
const readEventRowsByCommandId = SqlSchema.findAll({
|
|
24179
|
+
Request: ReadByCommandIdRequestSchema,
|
|
24180
|
+
Result: OrchestrationEventPersistedRowSchema,
|
|
24181
|
+
execute: ({ commandId }) => sql`
|
|
24182
|
+
SELECT
|
|
24183
|
+
sequence,
|
|
24184
|
+
event_id AS "eventId",
|
|
24185
|
+
event_type AS "type",
|
|
24186
|
+
aggregate_kind AS "aggregateKind",
|
|
24187
|
+
stream_id AS "aggregateId",
|
|
24188
|
+
occurred_at AS "occurredAt",
|
|
24189
|
+
command_id AS "commandId",
|
|
24190
|
+
causation_event_id AS "causationEventId",
|
|
24191
|
+
correlation_id AS "correlationId",
|
|
24192
|
+
payload_json AS "payload",
|
|
24193
|
+
metadata_json AS "metadata"
|
|
24194
|
+
FROM orchestration_events
|
|
24195
|
+
WHERE command_id = ${commandId}
|
|
24196
|
+
ORDER BY sequence ASC
|
|
24128
24197
|
`
|
|
24129
24198
|
});
|
|
24130
24199
|
const append = (event) => appendEventRow({
|
|
@@ -24154,8 +24223,10 @@ const makeEventStore = Effect.gen(function* () {
|
|
|
24154
24223
|
}));
|
|
24155
24224
|
return readPage(sequenceExclusive, normalizedLimit);
|
|
24156
24225
|
};
|
|
24226
|
+
const readByCommandId = (commandId) => readEventRowsByCommandId({ commandId }).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$4("OrchestrationEventStore.readByCommandId:query", "OrchestrationEventStore.readByCommandId:decodeRows")), Effect.flatMap((rows) => Effect.forEach(rows, (row) => decodeEvent(row).pipe(Effect.mapError(toPersistenceDecodeError("OrchestrationEventStore.readByCommandId:rowToEvent"))))));
|
|
24157
24227
|
return {
|
|
24158
24228
|
append,
|
|
24229
|
+
readByCommandId,
|
|
24159
24230
|
readFromSequence,
|
|
24160
24231
|
readAll: () => readFromSequence(0, Number.MAX_SAFE_INTEGER)
|
|
24161
24232
|
};
|
|
@@ -24856,6 +24927,9 @@ function projectEvent(model, event) {
|
|
|
24856
24927
|
//#endregion
|
|
24857
24928
|
//#region src/orchestration/decider.ts
|
|
24858
24929
|
const nowIso$8 = Effect.map(DateTime.now, DateTime.formatIso);
|
|
24930
|
+
function findActiveThreadPair(readModel, threadId) {
|
|
24931
|
+
return (readModel.threadPairs ?? []).find((pair) => pair.detachedAt === null && (pair.implementerThreadId === threadId || pair.watcherThreadId === threadId));
|
|
24932
|
+
}
|
|
24859
24933
|
const QUEUED_TURN_START_GRACE_MS = 120 * 1e3;
|
|
24860
24934
|
/**
|
|
24861
24935
|
* Blocked-on-you work derived from the thread's retained activities: an
|
|
@@ -25086,7 +25160,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
25086
25160
|
command,
|
|
25087
25161
|
threadId: command.threadId
|
|
25088
25162
|
});
|
|
25089
|
-
const activePair = (readModel
|
|
25163
|
+
const activePair = findActiveThreadPair(readModel, command.threadId);
|
|
25090
25164
|
if (activePair !== void 0) return yield* decideCommandSequence({
|
|
25091
25165
|
readModel,
|
|
25092
25166
|
commands: [{
|
|
@@ -25338,47 +25412,118 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
25338
25412
|
};
|
|
25339
25413
|
}
|
|
25340
25414
|
case "thread.archive": {
|
|
25341
|
-
|
|
25415
|
+
const activePair = findActiveThreadPair(readModel, command.threadId);
|
|
25416
|
+
if (activePair === void 0) {
|
|
25417
|
+
yield* requireThreadNotArchived({
|
|
25418
|
+
readModel,
|
|
25419
|
+
command,
|
|
25420
|
+
threadId: command.threadId
|
|
25421
|
+
});
|
|
25422
|
+
const occurredAt = yield* nowIso$8;
|
|
25423
|
+
return {
|
|
25424
|
+
...yield* withEventBase({
|
|
25425
|
+
aggregateKind: "thread",
|
|
25426
|
+
aggregateId: command.threadId,
|
|
25427
|
+
occurredAt,
|
|
25428
|
+
commandId: command.commandId
|
|
25429
|
+
}),
|
|
25430
|
+
type: "thread.archived",
|
|
25431
|
+
payload: {
|
|
25432
|
+
threadId: command.threadId,
|
|
25433
|
+
archivedAt: occurredAt,
|
|
25434
|
+
updatedAt: occurredAt
|
|
25435
|
+
}
|
|
25436
|
+
};
|
|
25437
|
+
}
|
|
25438
|
+
const occurredAt = yield* nowIso$8;
|
|
25439
|
+
const pairedThreads = [yield* requireThread({
|
|
25342
25440
|
readModel,
|
|
25343
25441
|
command,
|
|
25344
|
-
threadId:
|
|
25345
|
-
})
|
|
25346
|
-
const occurredAt = yield* nowIso$8;
|
|
25347
|
-
return {
|
|
25348
|
-
...yield* withEventBase({
|
|
25349
|
-
aggregateKind: "thread",
|
|
25350
|
-
aggregateId: command.threadId,
|
|
25351
|
-
occurredAt,
|
|
25352
|
-
commandId: command.commandId
|
|
25353
|
-
}),
|
|
25354
|
-
type: "thread.archived",
|
|
25355
|
-
payload: {
|
|
25356
|
-
threadId: command.threadId,
|
|
25357
|
-
archivedAt: occurredAt,
|
|
25358
|
-
updatedAt: occurredAt
|
|
25359
|
-
}
|
|
25360
|
-
};
|
|
25361
|
-
}
|
|
25362
|
-
case "thread.unarchive": {
|
|
25363
|
-
yield* requireThreadArchived({
|
|
25442
|
+
threadId: activePair.implementerThreadId
|
|
25443
|
+
}), yield* requireThread({
|
|
25364
25444
|
readModel,
|
|
25365
25445
|
command,
|
|
25366
|
-
threadId:
|
|
25367
|
-
});
|
|
25446
|
+
threadId: activePair.watcherThreadId
|
|
25447
|
+
})];
|
|
25448
|
+
const stopEvents = [];
|
|
25449
|
+
const archiveEvents = [];
|
|
25450
|
+
for (const thread of pairedThreads) {
|
|
25451
|
+
if (thread.session !== null && thread.session.status !== "stopped") stopEvents.push({
|
|
25452
|
+
...yield* withEventBase({
|
|
25453
|
+
aggregateKind: "thread",
|
|
25454
|
+
aggregateId: thread.id,
|
|
25455
|
+
occurredAt,
|
|
25456
|
+
commandId: command.commandId
|
|
25457
|
+
}),
|
|
25458
|
+
type: "thread.session-stop-requested",
|
|
25459
|
+
payload: {
|
|
25460
|
+
threadId: thread.id,
|
|
25461
|
+
createdAt: occurredAt
|
|
25462
|
+
}
|
|
25463
|
+
});
|
|
25464
|
+
archiveEvents.push({
|
|
25465
|
+
...yield* withEventBase({
|
|
25466
|
+
aggregateKind: "thread",
|
|
25467
|
+
aggregateId: thread.id,
|
|
25468
|
+
occurredAt,
|
|
25469
|
+
commandId: command.commandId
|
|
25470
|
+
}),
|
|
25471
|
+
type: "thread.archived",
|
|
25472
|
+
payload: {
|
|
25473
|
+
threadId: thread.id,
|
|
25474
|
+
archivedAt: thread.archivedAt ?? occurredAt,
|
|
25475
|
+
updatedAt: thread.archivedAt === null ? occurredAt : thread.updatedAt
|
|
25476
|
+
}
|
|
25477
|
+
});
|
|
25478
|
+
}
|
|
25479
|
+
return [...stopEvents, ...archiveEvents];
|
|
25480
|
+
}
|
|
25481
|
+
case "thread.unarchive": {
|
|
25482
|
+
const activePair = findActiveThreadPair(readModel, command.threadId);
|
|
25483
|
+
if (activePair === void 0) {
|
|
25484
|
+
yield* requireThreadArchived({
|
|
25485
|
+
readModel,
|
|
25486
|
+
command,
|
|
25487
|
+
threadId: command.threadId
|
|
25488
|
+
});
|
|
25489
|
+
const occurredAt = yield* nowIso$8;
|
|
25490
|
+
return {
|
|
25491
|
+
...yield* withEventBase({
|
|
25492
|
+
aggregateKind: "thread",
|
|
25493
|
+
aggregateId: command.threadId,
|
|
25494
|
+
occurredAt,
|
|
25495
|
+
commandId: command.commandId
|
|
25496
|
+
}),
|
|
25497
|
+
type: "thread.unarchived",
|
|
25498
|
+
payload: {
|
|
25499
|
+
threadId: command.threadId,
|
|
25500
|
+
updatedAt: occurredAt
|
|
25501
|
+
}
|
|
25502
|
+
};
|
|
25503
|
+
}
|
|
25368
25504
|
const occurredAt = yield* nowIso$8;
|
|
25369
|
-
|
|
25370
|
-
|
|
25371
|
-
|
|
25372
|
-
|
|
25373
|
-
|
|
25374
|
-
|
|
25375
|
-
})
|
|
25376
|
-
|
|
25377
|
-
|
|
25378
|
-
|
|
25379
|
-
|
|
25380
|
-
|
|
25381
|
-
|
|
25505
|
+
const events = [];
|
|
25506
|
+
for (const threadId of [activePair.implementerThreadId, activePair.watcherThreadId]) {
|
|
25507
|
+
const thread = yield* requireThread({
|
|
25508
|
+
readModel,
|
|
25509
|
+
command,
|
|
25510
|
+
threadId
|
|
25511
|
+
});
|
|
25512
|
+
events.push({
|
|
25513
|
+
...yield* withEventBase({
|
|
25514
|
+
aggregateKind: "thread",
|
|
25515
|
+
aggregateId: thread.id,
|
|
25516
|
+
occurredAt,
|
|
25517
|
+
commandId: command.commandId
|
|
25518
|
+
}),
|
|
25519
|
+
type: "thread.unarchived",
|
|
25520
|
+
payload: {
|
|
25521
|
+
threadId: thread.id,
|
|
25522
|
+
updatedAt: thread.archivedAt === null ? thread.updatedAt : occurredAt
|
|
25523
|
+
}
|
|
25524
|
+
});
|
|
25525
|
+
}
|
|
25526
|
+
return events;
|
|
25382
25527
|
}
|
|
25383
25528
|
case "thread.settle": {
|
|
25384
25529
|
const thread = yield* requireThreadNotArchived({
|
|
@@ -26195,7 +26340,13 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
26195
26340
|
});
|
|
26196
26341
|
const existingReceipt = yield* commandReceiptRepository.getByCommandId({ commandId: envelope.command.commandId });
|
|
26197
26342
|
if (Option.isSome(existingReceipt)) {
|
|
26198
|
-
if (existingReceipt.value.status === "accepted")
|
|
26343
|
+
if (existingReceipt.value.status === "accepted") {
|
|
26344
|
+
const events = yield* eventStore.readByCommandId(envelope.command.commandId);
|
|
26345
|
+
return {
|
|
26346
|
+
sequence: existingReceipt.value.resultSequence,
|
|
26347
|
+
events
|
|
26348
|
+
};
|
|
26349
|
+
}
|
|
26199
26350
|
return yield* new OrchestrationCommandPreviouslyRejectedError({
|
|
26200
26351
|
commandId: envelope.command.commandId,
|
|
26201
26352
|
detail: existingReceipt.value.error ?? "Previously rejected."
|
|
@@ -26247,7 +26398,10 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
26247
26398
|
ackEventType: event.type
|
|
26248
26399
|
})), Duration.millis(Math.max(0, (yield* Clock.currentTimeMillis) - envelope.startedAtMs)));
|
|
26249
26400
|
}
|
|
26250
|
-
return {
|
|
26401
|
+
return {
|
|
26402
|
+
sequence: committedCommand.lastSequence,
|
|
26403
|
+
events: committedCommand.committedEvents
|
|
26404
|
+
};
|
|
26251
26405
|
}).pipe(Effect.withSpan(`orchestration.command.${envelope.command.type}`))).pipe(Effect.flatMap((exit) => Effect.gen(function* () {
|
|
26252
26406
|
const outcome = Exit.isSuccess(exit) ? "success" : Cause.hasInterruptsOnly(exit.cause) ? "interrupt" : "failure";
|
|
26253
26407
|
yield* Metric.update(Metric.withAttributes(orchestrationCommandDuration, metricAttributes(baseMetricAttributes)), Duration.millis(Math.max(0, (yield* Clock.currentTimeMillis) - processingStartedAtMs)));
|
|
@@ -30903,8 +31057,9 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
30903
31057
|
listArchivedThreadRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreads:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreads:decodeRows"))),
|
|
30904
31058
|
listArchivedThreadSessionRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreadSessions:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreadSessions:decodeRows"))),
|
|
30905
31059
|
listArchivedLatestTurnRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listLatestTurns:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listLatestTurns:decodeRows"))),
|
|
30906
|
-
listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listProjectionState:decodeRows")))
|
|
30907
|
-
|
|
31060
|
+
listProjectionStateRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listProjectionState:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listProjectionState:decodeRows"))),
|
|
31061
|
+
listThreadPairRows(void 0).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreadPairs:query", "ProjectionSnapshotQuery.getArchivedShellSnapshot:listThreadPairs:decodeRows")))
|
|
31062
|
+
])).pipe(Effect.flatMap(([projectRows, threadRows, sessionRows, latestTurnRows, stateRows, threadPairRows]) => Effect.gen(function* () {
|
|
30908
31063
|
let updatedAt = null;
|
|
30909
31064
|
for (const row of projectRows) updatedAt = maxIso(updatedAt, row.updatedAt);
|
|
30910
31065
|
for (const row of threadRows) updatedAt = maxIso(updatedAt, row.updatedAt);
|
|
@@ -30919,6 +31074,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
30919
31074
|
const repositoryIdentities = yield* resolveRepositoryIdentitiesForProjects(projectRows.filter((row) => activeProjectIds.has(row.projectId)));
|
|
30920
31075
|
const latestTurnByThread = new Map(latestTurnRows.map((row) => [row.threadId, mapLatestTurn(row)]));
|
|
30921
31076
|
const sessionByThread = new Map(sessionRows.map((row) => [row.threadId, mapSessionRow(row)]));
|
|
31077
|
+
const archivedThreadIds = new Set(threadRows.map((row) => row.threadId));
|
|
30922
31078
|
const snapshot = {
|
|
30923
31079
|
snapshotSequence: computeSnapshotSequence(stateRows),
|
|
30924
31080
|
projects: Arr.filterMap(projectRows, (row) => row.deletedAt === null && activeProjectIds.has(row.projectId) ? Result.succeed(mapProjectShellRow(row, repositoryIdentities.get(row.projectId) ?? null)) : Result.failVoid),
|
|
@@ -30952,6 +31108,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
30952
31108
|
hasBackgroundTasks: row.backgroundTaskCount > 0,
|
|
30953
31109
|
scheduledWakeAt: row.scheduledWakeAt
|
|
30954
31110
|
})),
|
|
31111
|
+
threadPairs: threadPairRows.filter((pair) => pair.detachedAt === null && (archivedThreadIds.has(pair.implementerThreadId) || archivedThreadIds.has(pair.watcherThreadId))),
|
|
30955
31112
|
updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z"
|
|
30956
31113
|
};
|
|
30957
31114
|
return yield* decodeShellSnapshot(snapshot).pipe(Effect.mapError(toPersistenceDecodeError("ProjectionSnapshotQuery.getArchivedShellSnapshot:decodeShellSnapshot")));
|
|
@@ -31256,6 +31413,10 @@ const DEFAULT_KEYBINDINGS = [
|
|
|
31256
31413
|
key: "mod+shift+b",
|
|
31257
31414
|
command: "board.toggle"
|
|
31258
31415
|
},
|
|
31416
|
+
{
|
|
31417
|
+
key: "mod+alt+t",
|
|
31418
|
+
command: "todos.toggle"
|
|
31419
|
+
},
|
|
31259
31420
|
{
|
|
31260
31421
|
key: "mod+d",
|
|
31261
31422
|
command: "terminal.split",
|
|
@@ -41230,6 +41391,7 @@ const taskFromLinearIssue = (issue, link = EMPTY_LINEAR_TASK_LINK) => {
|
|
|
41230
41391
|
priority: priorityFromLinear(issue["priority"]),
|
|
41231
41392
|
assignee: personName(issue["assignee"]),
|
|
41232
41393
|
labels: labelNames(issue["labels"]),
|
|
41394
|
+
statusChangedAt: updatedAt ?? createdAt ?? "1970-01-01T00:00:00.000Z",
|
|
41233
41395
|
createdAt: createdAt ?? updatedAt ?? "1970-01-01T00:00:00.000Z",
|
|
41234
41396
|
updatedAt: updatedAt ?? createdAt ?? "1970-01-01T00:00:00.000Z"
|
|
41235
41397
|
};
|
|
@@ -41621,6 +41783,7 @@ const makeHubTaskClient = Effect.gen(function* () {
|
|
|
41621
41783
|
labels: row.labels,
|
|
41622
41784
|
orderKey: row.orderKey,
|
|
41623
41785
|
createdAt: row.createdAt,
|
|
41786
|
+
statusChangedAt: row.statusChangedAt ?? row.updatedAt,
|
|
41624
41787
|
readableIdPrefix
|
|
41625
41788
|
}));
|
|
41626
41789
|
if (response.status !== 200 && response.status !== 201) return yield* hubUnavailable("put", `status ${response.status}`);
|
|
@@ -41692,6 +41855,7 @@ const TASK_COLUMNS = `
|
|
|
41692
41855
|
assignee,
|
|
41693
41856
|
labels_json AS "labels",
|
|
41694
41857
|
order_key AS "orderKey",
|
|
41858
|
+
status_changed_at AS "statusChangedAt",
|
|
41695
41859
|
created_at AS "createdAt",
|
|
41696
41860
|
updated_at AS "updatedAt"
|
|
41697
41861
|
`;
|
|
@@ -42071,6 +42235,7 @@ const buildTaskRow = (input, taskId, timestamp, repositoryKey = null) => ({
|
|
|
42071
42235
|
assignee: input.assignee ?? null,
|
|
42072
42236
|
labels: input.labels ?? [],
|
|
42073
42237
|
orderKey: null,
|
|
42238
|
+
statusChangedAt: timestamp,
|
|
42074
42239
|
createdAt: timestamp,
|
|
42075
42240
|
updatedAt: timestamp
|
|
42076
42241
|
});
|
|
@@ -62303,7 +62468,12 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
62303
62468
|
})), Effect.orElseSucceed(() => false)) : false;
|
|
62304
62469
|
const result = yield* dispatchNormalizedCommand(normalizedCommand);
|
|
62305
62470
|
if (normalizedCommand.type === "thread.archive") {
|
|
62306
|
-
|
|
62471
|
+
const archivedThreadIds = result.events?.filter((event) => event.type === "thread.archived").map((event) => event.payload.threadId);
|
|
62472
|
+
if (archivedThreadIds === void 0 || archivedThreadIds.length === 0) return yield* new OrchestrationDispatchCommandError({ message: "Archive command completed without authoritative archive events." });
|
|
62473
|
+
const uniqueArchivedThreadIds = Array.from(new Set(archivedThreadIds));
|
|
62474
|
+
const pairedArchive = uniqueArchivedThreadIds.length > 1;
|
|
62475
|
+
if (!uniqueArchivedThreadIds.includes(normalizedCommand.threadId)) return yield* new OrchestrationDispatchCommandError({ message: "Archive command result did not include the requested thread." });
|
|
62476
|
+
if (shouldStopSessionAfterArchive && !pairedArchive) yield* Effect.gen(function* () {
|
|
62307
62477
|
const stopCommand = yield* normalizeDispatchCommand({
|
|
62308
62478
|
type: "thread.session.stop",
|
|
62309
62479
|
commandId: CommandId.make(`session-stop-for-archive:${normalizedCommand.commandId}`),
|
|
@@ -62315,12 +62485,12 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
62315
62485
|
threadId: normalizedCommand.threadId,
|
|
62316
62486
|
cause
|
|
62317
62487
|
})));
|
|
62318
|
-
yield* terminalManager.close({ threadId
|
|
62319
|
-
threadId
|
|
62488
|
+
yield* Effect.forEach(uniqueArchivedThreadIds, (threadId) => terminalManager.close({ threadId }).pipe(Effect.catch((error) => Effect.logWarning("failed to close thread terminals after archive", {
|
|
62489
|
+
threadId,
|
|
62320
62490
|
error: error.message
|
|
62321
|
-
})));
|
|
62491
|
+
}))), { discard: true });
|
|
62322
62492
|
}
|
|
62323
|
-
return result;
|
|
62493
|
+
return { sequence: result.sequence };
|
|
62324
62494
|
}).pipe(Effect.mapError((cause) => isOrchestrationDispatchCommandError(cause) ? cause : new OrchestrationDispatchCommandError({
|
|
62325
62495
|
message: "Failed to dispatch orchestration command",
|
|
62326
62496
|
cause
|
|
@@ -87876,6 +88046,17 @@ function parseCodexSkillsListResponse(response, cwd) {
|
|
|
87876
88046
|
return parsedSkill;
|
|
87877
88047
|
});
|
|
87878
88048
|
}
|
|
88049
|
+
/** Codex omits unknown SKILL.md frontmatter, so enrich its snapshot from each advertised path. */
|
|
88050
|
+
const enrichCodexSkillsWithFrontmatter = Effect.fnUntraced(function* (skills) {
|
|
88051
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
88052
|
+
return yield* Effect.forEach(skills, (skill) => fileSystem.readFileString(skill.path).pipe(Effect.map((contents) => {
|
|
88053
|
+
const frontmatter = parseMarkdownFrontmatter(contents);
|
|
88054
|
+
return frontmatter.kind === "parsed" && frontmatter.requiredInteractionMode ? {
|
|
88055
|
+
...skill,
|
|
88056
|
+
requiredInteractionMode: frontmatter.requiredInteractionMode
|
|
88057
|
+
} : skill;
|
|
88058
|
+
}), Effect.orElseSucceed(() => skill)), { concurrency: "unbounded" });
|
|
88059
|
+
});
|
|
87879
88060
|
const requestAllCodexModels = Effect.fn("requestAllCodexModels")(function* (client) {
|
|
87880
88061
|
const models = [];
|
|
87881
88062
|
let cursor = void 0;
|
|
@@ -87938,11 +88119,12 @@ const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(fun
|
|
|
87938
88119
|
skills: []
|
|
87939
88120
|
};
|
|
87940
88121
|
const [skillsResponse, models] = yield* Effect.all([client.request("skills/list", { cwds: [input.cwd] }), requestAllCodexModels(client)], { concurrency: "unbounded" });
|
|
88122
|
+
const skills = yield* enrichCodexSkillsWithFrontmatter(parseCodexSkillsListResponse(skillsResponse, input.cwd));
|
|
87941
88123
|
return {
|
|
87942
88124
|
account: accountResponse,
|
|
87943
88125
|
version,
|
|
87944
88126
|
models: applyPreferredCodexDefaultModel(appendCustomCodexModels(models, input.customModels ?? [])),
|
|
87945
|
-
skills
|
|
88127
|
+
skills
|
|
87946
88128
|
};
|
|
87947
88129
|
});
|
|
87948
88130
|
const emptyCodexModelsFromSettings = (codexSettings) => {
|
|
@@ -90583,6 +90765,7 @@ const CodexDriver = {
|
|
|
90583
90765
|
defaultConfig: () => decodeCodexSettings({}),
|
|
90584
90766
|
create: ({ instanceId, displayName, accentColor, environment, enabled, config }) => Effect.gen(function* () {
|
|
90585
90767
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
90768
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
90586
90769
|
const httpClient = yield* HttpClient.HttpClient;
|
|
90587
90770
|
const serverSettings = yield* ServerSettingsService;
|
|
90588
90771
|
const eventLoggers = yield* ProviderEventLoggers;
|
|
@@ -90617,7 +90800,7 @@ const CodexDriver = {
|
|
|
90617
90800
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
|
|
90618
90801
|
});
|
|
90619
90802
|
const textGeneration = yield* makeCodexTextGeneration(effectiveConfig, processEnv);
|
|
90620
|
-
const checkProvider = checkCodexProviderStatus(effectiveConfig, void 0, processEnv).pipe(Effect.map(stampIdentity), Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner));
|
|
90803
|
+
const checkProvider = checkCodexProviderStatus(effectiveConfig, void 0, processEnv).pipe(Effect.map(stampIdentity), Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), Effect.provideService(FileSystem.FileSystem, fileSystem));
|
|
90621
90804
|
const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
|
|
90622
90805
|
const snapshot = yield* makeManagedServerProvider({
|
|
90623
90806
|
maintenanceCapabilities,
|
|
@@ -105238,18 +105421,18 @@ const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionServic
|
|
|
105238
105421
|
* @module provider/userInvokedSkills
|
|
105239
105422
|
*/
|
|
105240
105423
|
/**
|
|
105241
|
-
* A leading `/name`, with whatever followed it.
|
|
105424
|
+
* A leading `/name` or `$name`, with whatever followed it.
|
|
105242
105425
|
*
|
|
105243
|
-
* Anchored at the start: a
|
|
105244
|
-
*
|
|
105426
|
+
* Anchored at the start: a marker somewhere inside a sentence can be a path,
|
|
105427
|
+
* date, currency, or prose, and treating it as a command would rewrite ordinary
|
|
105245
105428
|
* messages. The name pattern matches what a skill directory can be called,
|
|
105246
105429
|
* including the `plugin:skill` form.
|
|
105247
105430
|
*/
|
|
105248
|
-
const
|
|
105431
|
+
const SKILL_INVOCATION = /^[/$]([A-Za-z0-9][A-Za-z0-9_:-]*)[ \t]*([\s\S]*)$/;
|
|
105249
105432
|
/** `SKILL.md` is the only file a skill is required to have. */
|
|
105250
105433
|
const SKILL_FILENAME = "SKILL.md";
|
|
105251
105434
|
const parseSlashInvocation = (text) => {
|
|
105252
|
-
const match =
|
|
105435
|
+
const match = SKILL_INVOCATION.exec(text.trim());
|
|
105253
105436
|
const name = match?.[1];
|
|
105254
105437
|
if (name === void 0) return void 0;
|
|
105255
105438
|
return {
|
|
@@ -105533,7 +105716,7 @@ const make$3 = Effect.gen(function* () {
|
|
|
105533
105716
|
return yield* projectionSnapshotQuery.getProjectShellById(projectId).pipe(Effect.map(Option.getOrUndefined));
|
|
105534
105717
|
});
|
|
105535
105718
|
/**
|
|
105536
|
-
* Where a typed `/name` is looked up: the user's skills, then the
|
|
105719
|
+
* Where a typed `/name` or `$name` is looked up: the user's skills, then the
|
|
105537
105720
|
* workspace's.
|
|
105538
105721
|
*
|
|
105539
105722
|
* Project last so it wins, matching the CLI's most-specific-wins resolution.
|