@basou/core 0.6.0 → 0.8.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.
- package/dist/index.d.ts +73 -5
- package/dist/index.js +158 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/manifest.schema.json +14 -0
- package/schemas/session-import.schema.json +6 -1
- package/schemas/session.schema.json +5 -0
package/dist/index.d.ts
CHANGED
|
@@ -89,6 +89,9 @@ declare const ManifestSchema: z.ZodObject<{
|
|
|
89
89
|
commit: "commit";
|
|
90
90
|
}>>;
|
|
91
91
|
}, z.core.$strip>;
|
|
92
|
+
import: z.ZodOptional<z.ZodObject<{
|
|
93
|
+
source_roots: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
92
95
|
}, z.core.$strip>;
|
|
93
96
|
/** Inferred runtime type for {@link ManifestSchema}. */
|
|
94
97
|
type Manifest = z.infer<typeof ManifestSchema>;
|
|
@@ -101,14 +104,15 @@ declare const SessionInnerImportSchema: z.ZodObject<{
|
|
|
101
104
|
source: z.ZodObject<{
|
|
102
105
|
kind: z.ZodEnum<{
|
|
103
106
|
"claude-code-adapter": "claude-code-adapter";
|
|
107
|
+
import: "import";
|
|
104
108
|
"claude-code-import": "claude-code-import";
|
|
105
109
|
"codex-import": "codex-import";
|
|
106
110
|
human: "human";
|
|
107
|
-
import: "import";
|
|
108
111
|
terminal: "terminal";
|
|
109
112
|
}>;
|
|
110
113
|
version: z.ZodLiteral<"0.1.0">;
|
|
111
114
|
external_id: z.ZodOptional<z.ZodString>;
|
|
115
|
+
source_size_bytes: z.ZodOptional<z.ZodNumber>;
|
|
112
116
|
}, z.core.$strip>;
|
|
113
117
|
started_at: z.ZodString;
|
|
114
118
|
ended_at: z.ZodOptional<z.ZodString>;
|
|
@@ -161,14 +165,15 @@ declare const SessionImportPayloadSchema: z.ZodObject<{
|
|
|
161
165
|
source: z.ZodObject<{
|
|
162
166
|
kind: z.ZodEnum<{
|
|
163
167
|
"claude-code-adapter": "claude-code-adapter";
|
|
168
|
+
import: "import";
|
|
164
169
|
"claude-code-import": "claude-code-import";
|
|
165
170
|
"codex-import": "codex-import";
|
|
166
171
|
human: "human";
|
|
167
|
-
import: "import";
|
|
168
172
|
terminal: "terminal";
|
|
169
173
|
}>;
|
|
170
174
|
version: z.ZodLiteral<"0.1.0">;
|
|
171
175
|
external_id: z.ZodOptional<z.ZodString>;
|
|
176
|
+
source_size_bytes: z.ZodOptional<z.ZodNumber>;
|
|
172
177
|
}, z.core.$strip>;
|
|
173
178
|
started_at: z.ZodString;
|
|
174
179
|
ended_at: z.ZodOptional<z.ZodString>;
|
|
@@ -448,6 +453,14 @@ type ClaudeTranscriptToPayloadOptions = {
|
|
|
448
453
|
* back to the `sessionId` read from the records when omitted.
|
|
449
454
|
*/
|
|
450
455
|
externalId?: string;
|
|
456
|
+
/**
|
|
457
|
+
* Byte size of the source transcript that produced `records`, stored as
|
|
458
|
+
* `session.source.source_size_bytes` so a later import can detect growth and
|
|
459
|
+
* re-import the session. The caller passes the size of the buffer it actually
|
|
460
|
+
* read (an immutable snapshot of the parsed bytes), so the stored size always
|
|
461
|
+
* matches the imported content. Omitted => the field is not recorded.
|
|
462
|
+
*/
|
|
463
|
+
sourceSizeBytes?: number;
|
|
451
464
|
};
|
|
452
465
|
/**
|
|
453
466
|
* Transform a Claude Code native transcript into a Basou
|
|
@@ -503,6 +516,14 @@ type CodexRolloutToPayloadOptions = {
|
|
|
503
516
|
* to the id read from the rollout's `session_meta` record when omitted.
|
|
504
517
|
*/
|
|
505
518
|
externalId?: string;
|
|
519
|
+
/**
|
|
520
|
+
* Byte size of the source rollout that produced `records`, stored as
|
|
521
|
+
* `session.source.source_size_bytes` so a later import can detect growth and
|
|
522
|
+
* re-import the session. The caller passes the size of the buffer it actually
|
|
523
|
+
* read (an immutable snapshot of the parsed bytes), so the stored size always
|
|
524
|
+
* matches the imported content. Omitted => the field is not recorded.
|
|
525
|
+
*/
|
|
526
|
+
sourceSizeBytes?: number;
|
|
506
527
|
};
|
|
507
528
|
/**
|
|
508
529
|
* Transform a Codex native rollout log into a Basou {@link SessionImportPayload},
|
|
@@ -1271,10 +1292,10 @@ type SessionStatus = z.infer<typeof SessionStatusSchema>;
|
|
|
1271
1292
|
*/
|
|
1272
1293
|
declare const SessionSourceKindSchema: z.ZodEnum<{
|
|
1273
1294
|
"claude-code-adapter": "claude-code-adapter";
|
|
1295
|
+
import: "import";
|
|
1274
1296
|
"claude-code-import": "claude-code-import";
|
|
1275
1297
|
"codex-import": "codex-import";
|
|
1276
1298
|
human: "human";
|
|
1277
|
-
import: "import";
|
|
1278
1299
|
terminal: "terminal";
|
|
1279
1300
|
}>;
|
|
1280
1301
|
/** Inferred runtime type for {@link SessionSourceKindSchema}. */
|
|
@@ -1339,14 +1360,15 @@ declare const SessionSchema: z.ZodObject<{
|
|
|
1339
1360
|
source: z.ZodObject<{
|
|
1340
1361
|
kind: z.ZodEnum<{
|
|
1341
1362
|
"claude-code-adapter": "claude-code-adapter";
|
|
1363
|
+
import: "import";
|
|
1342
1364
|
"claude-code-import": "claude-code-import";
|
|
1343
1365
|
"codex-import": "codex-import";
|
|
1344
1366
|
human: "human";
|
|
1345
|
-
import: "import";
|
|
1346
1367
|
terminal: "terminal";
|
|
1347
1368
|
}>;
|
|
1348
1369
|
version: z.ZodLiteral<"0.1.0">;
|
|
1349
1370
|
external_id: z.ZodOptional<z.ZodString>;
|
|
1371
|
+
source_size_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1350
1372
|
}, z.core.$strip>;
|
|
1351
1373
|
started_at: z.ZodString;
|
|
1352
1374
|
ended_at: z.ZodOptional<z.ZodString>;
|
|
@@ -3146,6 +3168,14 @@ type CreateManifestInput = {
|
|
|
3146
3168
|
now?: Date;
|
|
3147
3169
|
/** Override for tests; defaults to a freshly generated `ws_<ULID>`. */
|
|
3148
3170
|
workspaceId?: PrefixedId<"ws">;
|
|
3171
|
+
/**
|
|
3172
|
+
* Import source roots, each RELATIVE to the repository root (e.g. `"."`,
|
|
3173
|
+
* `"../basou-workspace"`). Persisted under `import.source_roots` so
|
|
3174
|
+
* `basou refresh` / `basou import` aggregate several sibling repos into one
|
|
3175
|
+
* `.basou/`. Validated by `ManifestSchema` (absolute paths are rejected).
|
|
3176
|
+
* Omitted from the manifest entirely when absent or empty.
|
|
3177
|
+
*/
|
|
3178
|
+
sourceRoots?: string[];
|
|
3149
3179
|
};
|
|
3150
3180
|
/**
|
|
3151
3181
|
* Build a fresh Manifest object that satisfies the manifest schema's
|
|
@@ -3295,6 +3325,44 @@ type ImportSessionResult = {
|
|
|
3295
3325
|
* for `--verbose` rendering.
|
|
3296
3326
|
*/
|
|
3297
3327
|
declare function importSessionFromJson(paths: BasouPaths, manifest: Manifest, payload: SessionImportPayload, options: ImportSessionOptions): Promise<ImportSessionResult>;
|
|
3328
|
+
/** Whether `source` is one of the known import-derived event sources. */
|
|
3329
|
+
declare function isImportDerivedSource(source: string): boolean;
|
|
3330
|
+
/** Options for {@link reimportPreservingId}. */
|
|
3331
|
+
type ReimportOptions = {
|
|
3332
|
+
/** Compute the re-import and return its preview without writing to disk. */
|
|
3333
|
+
dryRun?: boolean;
|
|
3334
|
+
};
|
|
3335
|
+
/** Result of {@link reimportPreservingId}. */
|
|
3336
|
+
type ReimportResult = {
|
|
3337
|
+
status: "reimported";
|
|
3338
|
+
sessionId: PrefixedId<"ses">;
|
|
3339
|
+
/** Total events written to the merged `events.jsonl`. */
|
|
3340
|
+
eventCount: number;
|
|
3341
|
+
/** Non-derived events (human / unknown source) carried over unchanged. */
|
|
3342
|
+
preservedCount: number;
|
|
3343
|
+
/** Derived events whose prior id (and decision_id) was reused. */
|
|
3344
|
+
reusedIdCount: number;
|
|
3345
|
+
} | {
|
|
3346
|
+
status: "skipped";
|
|
3347
|
+
reason: "prior_events_unreadable" | "prior_derived_dropped";
|
|
3348
|
+
};
|
|
3349
|
+
/**
|
|
3350
|
+
* Re-import a source whose native log GREW into the SAME Basou session,
|
|
3351
|
+
* preserving its id and any non-derived events, instead of skipping it (default
|
|
3352
|
+
* dedup) or deleting + recreating it (`--force`). The caller has already
|
|
3353
|
+
* validated `freshPayload` and confirmed (by source byte size) that the source
|
|
3354
|
+
* changed; this function re-derives the adapter's events, reuses prior derived
|
|
3355
|
+
* event ids for unchanged derivations (so `linked_events` references survive),
|
|
3356
|
+
* preserves human / unknown-source events, and rewrites `events.jsonl` +
|
|
3357
|
+
* `session.yaml` atomically under the session lock.
|
|
3358
|
+
*
|
|
3359
|
+
* The whole read-modify-write runs under {@link acquireLock} so a concurrent
|
|
3360
|
+
* writer cannot interleave; `dryRun` computes the result and writes nothing
|
|
3361
|
+
* (and takes no lock). If the prior `events.jsonl` has any line that cannot be
|
|
3362
|
+
* preserved (malformed / schema-invalid / half-written), the re-import is
|
|
3363
|
+
* ABORTED (`status: "skipped"`) rather than risk dropping data on the rewrite.
|
|
3364
|
+
*/
|
|
3365
|
+
declare function reimportPreservingId(paths: BasouPaths, manifest: Manifest, priorSessionId: string, freshPayload: SessionImportPayload, options?: ReimportOptions): Promise<ReimportResult>;
|
|
3298
3366
|
|
|
3299
3367
|
/**
|
|
3300
3368
|
* Walk the cause chain (up to `depth` levels) looking for an Error whose
|
|
@@ -3396,4 +3464,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
|
|
|
3396
3464
|
*/
|
|
3397
3465
|
declare const BASOU_CORE_VERSION = "0.1.0";
|
|
3398
3466
|
|
|
3399
|
-
export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type PrefixedId, type ProcessRunner, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReplayOptions, type ReplayWarning, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, findErrorCode, getDiff, getSnapshot, importSessionFromJson, isLazyExpired, isValidPrefixedId, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, renderDecisions, renderHandoff, renderWithMarkers, replayEvents, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, tryRemoteUrl, ulid, updateTaskStatusWithEvent, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|
|
3467
|
+
export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type PrefixedId, type ProcessRunner, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type ReplayOptions, type ReplayWarning, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, findErrorCode, getDiff, getSnapshot, importSessionFromJson, isImportDerivedSource, isLazyExpired, isValidPrefixedId, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, renderDecisions, renderHandoff, renderWithMarkers, replayEvents, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, tryRemoteUrl, ulid, updateTaskStatusWithEvent, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|
package/dist/index.js
CHANGED
|
@@ -224,7 +224,8 @@ function claudeTranscriptToImportPayload(records, options) {
|
|
|
224
224
|
source: {
|
|
225
225
|
kind: CLAUDE_IMPORT_SOURCE,
|
|
226
226
|
version: "0.1.0",
|
|
227
|
-
...externalId !== void 0 ? { external_id: externalId } : {}
|
|
227
|
+
...externalId !== void 0 ? { external_id: externalId } : {},
|
|
228
|
+
...options.sourceSizeBytes !== void 0 ? { source_size_bytes: options.sourceSizeBytes } : {}
|
|
228
229
|
},
|
|
229
230
|
started_at: minTs,
|
|
230
231
|
ended_at: maxTs,
|
|
@@ -457,7 +458,8 @@ function codexRolloutToImportPayload(records, options) {
|
|
|
457
458
|
source: {
|
|
458
459
|
kind: CODEX_IMPORT_SOURCE,
|
|
459
460
|
version: "0.1.0",
|
|
460
|
-
...externalId !== void 0 ? { external_id: externalId } : {}
|
|
461
|
+
...externalId !== void 0 ? { external_id: externalId } : {},
|
|
462
|
+
...options.sourceSizeBytes !== void 0 ? { source_size_bytes: options.sourceSizeBytes } : {}
|
|
461
463
|
},
|
|
462
464
|
started_at: minTs,
|
|
463
465
|
ended_at: maxTs,
|
|
@@ -1032,7 +1034,15 @@ var SessionSourceSchema = z4.object({
|
|
|
1032
1034
|
// Optional id of the originating session in the SOURCE tool's own
|
|
1033
1035
|
// namespace (e.g. the Claude Code session UUID for a `claude-code-import`).
|
|
1034
1036
|
// Lets re-imports of the same source be deduplicated; absent for live runs.
|
|
1035
|
-
external_id: z4.string().optional()
|
|
1037
|
+
external_id: z4.string().optional(),
|
|
1038
|
+
// Byte size of the source native log at import time, recorded so a later
|
|
1039
|
+
// import can detect that an append-only transcript GREW and re-import it
|
|
1040
|
+
// (scoped, preserving the session id) instead of skipping it as already
|
|
1041
|
+
// imported. Additive optional => no schema_version bump (precedent:
|
|
1042
|
+
// external_id, metrics). Absent on sessions imported before this field
|
|
1043
|
+
// existed (treated as legacy: never auto-re-imported, populated on the next
|
|
1044
|
+
// fresh import or `--force`).
|
|
1045
|
+
source_size_bytes: z4.number().int().nonnegative().optional()
|
|
1036
1046
|
});
|
|
1037
1047
|
var InvocationSchema = z4.object({
|
|
1038
1048
|
command: z4.string().min(1),
|
|
@@ -3885,6 +3895,13 @@ var AdaptersSchema = z9.object({
|
|
|
3885
3895
|
var GitConfigSchema = z9.object({
|
|
3886
3896
|
events_log: z9.enum(["ignore", "commit"]).default("ignore")
|
|
3887
3897
|
});
|
|
3898
|
+
var SOURCE_ROOT_PATTERN = /^(?![~/\\])(?![A-Za-z]:)[^\0\\]+$/;
|
|
3899
|
+
var SourceRootSchema = z9.string().min(1).regex(SOURCE_ROOT_PATTERN, {
|
|
3900
|
+
message: "source_roots entries must be relative paths (no absolute path, '~', '\\', or null byte)"
|
|
3901
|
+
});
|
|
3902
|
+
var ImportConfigSchema = z9.object({
|
|
3903
|
+
source_roots: z9.array(SourceRootSchema).min(1).optional()
|
|
3904
|
+
});
|
|
3888
3905
|
var WorkspaceMetaSchema = z9.object({
|
|
3889
3906
|
id: WorkspaceIdSchema,
|
|
3890
3907
|
name: z9.string().min(1),
|
|
@@ -3899,7 +3916,8 @@ var ManifestSchema = z9.object({
|
|
|
3899
3916
|
capabilities: CapabilitiesSchema,
|
|
3900
3917
|
approval: ApprovalConfigSchema,
|
|
3901
3918
|
adapters: AdaptersSchema,
|
|
3902
|
-
git: GitConfigSchema
|
|
3919
|
+
git: GitConfigSchema,
|
|
3920
|
+
import: ImportConfigSchema.optional()
|
|
3903
3921
|
});
|
|
3904
3922
|
|
|
3905
3923
|
// src/schemas/session-import.schema.ts
|
|
@@ -3914,7 +3932,13 @@ var SessionInnerImportSchema = z10.object({
|
|
|
3914
3932
|
version: z10.literal("0.1.0"),
|
|
3915
3933
|
// Source-tool-native id (e.g. Claude Code session UUID), retained so
|
|
3916
3934
|
// re-imports of the same source can be deduplicated.
|
|
3917
|
-
external_id: z10.string().optional()
|
|
3935
|
+
external_id: z10.string().optional(),
|
|
3936
|
+
// Byte size of the source native log at import time. Declared here too
|
|
3937
|
+
// (not only in session.schema.ts) because this inner `source` object is
|
|
3938
|
+
// a plain z.object: zod strips keys it does not declare, so a field
|
|
3939
|
+
// absent here would be dropped from the parsed payload before persist
|
|
3940
|
+
// and the size could never be stored.
|
|
3941
|
+
source_size_bytes: z10.number().int().nonnegative().optional()
|
|
3918
3942
|
}),
|
|
3919
3943
|
started_at: IsoTimestampSchema,
|
|
3920
3944
|
ended_at: IsoTimestampSchema.optional(),
|
|
@@ -3987,7 +4011,7 @@ var DOCUMENTS = [
|
|
|
3987
4011
|
name: "session-import",
|
|
3988
4012
|
schema: SessionImportPayloadSchema,
|
|
3989
4013
|
title: "Basou Session Import Payload",
|
|
3990
|
-
description: "The portable session payload consumed by `basou session import
|
|
4014
|
+
description: "The portable session payload consumed by `basou session import`."
|
|
3991
4015
|
}
|
|
3992
4016
|
];
|
|
3993
4017
|
function buildJsonSchemas() {
|
|
@@ -4454,7 +4478,8 @@ function createManifest(input) {
|
|
|
4454
4478
|
adapters: {
|
|
4455
4479
|
"claude-code": { enabled: true }
|
|
4456
4480
|
},
|
|
4457
|
-
git: { events_log: "ignore" }
|
|
4481
|
+
git: { events_log: "ignore" },
|
|
4482
|
+
...input.sourceRoots !== void 0 && input.sourceRoots.length > 0 ? { import: { source_roots: input.sourceRoots } } : {}
|
|
4458
4483
|
};
|
|
4459
4484
|
return ManifestSchema.parse(manifest);
|
|
4460
4485
|
}
|
|
@@ -4722,6 +4747,130 @@ function buildSessionRecord(input, manifest, newSessionId, options) {
|
|
|
4722
4747
|
}
|
|
4723
4748
|
};
|
|
4724
4749
|
}
|
|
4750
|
+
var IMPORT_DERIVED_SOURCES = /* @__PURE__ */ new Set([
|
|
4751
|
+
"claude-code-import",
|
|
4752
|
+
"codex-import"
|
|
4753
|
+
]);
|
|
4754
|
+
function isImportDerivedSource(source) {
|
|
4755
|
+
return IMPORT_DERIVED_SOURCES.has(source);
|
|
4756
|
+
}
|
|
4757
|
+
function derivedEventContentKey(event) {
|
|
4758
|
+
const base = `${event.type}\0${event.occurred_at}`;
|
|
4759
|
+
switch (event.type) {
|
|
4760
|
+
case "command_executed":
|
|
4761
|
+
return `${base}\0${event.command}\0${event.args.join("")}\0${event.cwd}`;
|
|
4762
|
+
case "file_changed":
|
|
4763
|
+
return `${base}\0${event.path}\0${event.change_type}`;
|
|
4764
|
+
case "decision_recorded":
|
|
4765
|
+
return `${base}\0${event.title}`;
|
|
4766
|
+
default:
|
|
4767
|
+
return base;
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
function reuseDerivedIds(priorDerived, freshDerived, sessionId) {
|
|
4771
|
+
const priorStarted = priorDerived.find((e) => e.type === "session_started");
|
|
4772
|
+
const priorEnded = priorDerived.find((e) => e.type === "session_ended");
|
|
4773
|
+
let startedUsed = false;
|
|
4774
|
+
let endedUsed = false;
|
|
4775
|
+
const middleByKey = /* @__PURE__ */ new Map();
|
|
4776
|
+
for (const e of priorDerived) {
|
|
4777
|
+
if (e.type === "session_started" || e.type === "session_ended") continue;
|
|
4778
|
+
const key = derivedEventContentKey(e);
|
|
4779
|
+
const list = middleByKey.get(key);
|
|
4780
|
+
if (list === void 0) middleByKey.set(key, [e]);
|
|
4781
|
+
else list.push(e);
|
|
4782
|
+
}
|
|
4783
|
+
let reusedIdCount = 0;
|
|
4784
|
+
const withReusedId = (fresh, prior) => {
|
|
4785
|
+
reusedIdCount++;
|
|
4786
|
+
if (fresh.type === "decision_recorded" && prior.type === "decision_recorded") {
|
|
4787
|
+
return { ...fresh, id: prior.id, session_id: sessionId, decision_id: prior.decision_id };
|
|
4788
|
+
}
|
|
4789
|
+
return { ...fresh, id: prior.id, session_id: sessionId };
|
|
4790
|
+
};
|
|
4791
|
+
const events = freshDerived.map((fresh) => {
|
|
4792
|
+
if (fresh.type === "session_started") {
|
|
4793
|
+
if (priorStarted !== void 0) {
|
|
4794
|
+
startedUsed = true;
|
|
4795
|
+
return withReusedId(fresh, priorStarted);
|
|
4796
|
+
}
|
|
4797
|
+
return { ...fresh, id: prefixedUlid("evt"), session_id: sessionId };
|
|
4798
|
+
}
|
|
4799
|
+
if (fresh.type === "session_ended") {
|
|
4800
|
+
if (priorEnded !== void 0) {
|
|
4801
|
+
endedUsed = true;
|
|
4802
|
+
return withReusedId(fresh, priorEnded);
|
|
4803
|
+
}
|
|
4804
|
+
return { ...fresh, id: prefixedUlid("evt"), session_id: sessionId };
|
|
4805
|
+
}
|
|
4806
|
+
const match = middleByKey.get(derivedEventContentKey(fresh))?.shift();
|
|
4807
|
+
if (match !== void 0) return withReusedId(fresh, match);
|
|
4808
|
+
return { ...fresh, id: prefixedUlid("evt"), session_id: sessionId };
|
|
4809
|
+
});
|
|
4810
|
+
const droppedPriorDerived = priorStarted !== void 0 && !startedUsed || priorEnded !== void 0 && !endedUsed || [...middleByKey.values()].some((q) => q.length > 0);
|
|
4811
|
+
return { events, reusedIdCount, droppedPriorDerived };
|
|
4812
|
+
}
|
|
4813
|
+
async function reimportPreservingId(paths, manifest, priorSessionId, freshPayload, options = {}) {
|
|
4814
|
+
const sessionId = priorSessionId;
|
|
4815
|
+
const importSource = freshPayload.session.source.kind;
|
|
4816
|
+
const sessionDir = join14(paths.sessions, priorSessionId);
|
|
4817
|
+
const lock = options.dryRun === true ? null : await acquireLock(paths, "session", priorSessionId);
|
|
4818
|
+
try {
|
|
4819
|
+
let priorUnreadable = false;
|
|
4820
|
+
const priorEvents = await readAllEvents(sessionDir, {
|
|
4821
|
+
onWarning: () => {
|
|
4822
|
+
priorUnreadable = true;
|
|
4823
|
+
}
|
|
4824
|
+
});
|
|
4825
|
+
if (priorUnreadable) {
|
|
4826
|
+
return { status: "skipped", reason: "prior_events_unreadable" };
|
|
4827
|
+
}
|
|
4828
|
+
const priorDerived = priorEvents.filter((e) => e.source === importSource);
|
|
4829
|
+
const preserved = priorEvents.filter((e) => e.source !== importSource);
|
|
4830
|
+
const {
|
|
4831
|
+
events: rederived,
|
|
4832
|
+
reusedIdCount,
|
|
4833
|
+
droppedPriorDerived
|
|
4834
|
+
} = reuseDerivedIds(priorDerived, freshPayload.events, sessionId);
|
|
4835
|
+
if (droppedPriorDerived) {
|
|
4836
|
+
return { status: "skipped", reason: "prior_derived_dropped" };
|
|
4837
|
+
}
|
|
4838
|
+
const mergedEvents = [...rederived, ...preserved].sort(
|
|
4839
|
+
(a, b) => Date.parse(a.occurred_at) - Date.parse(b.occurred_at)
|
|
4840
|
+
);
|
|
4841
|
+
assertChronologicalOrder(mergedEvents);
|
|
4842
|
+
const prior = await readSessionYaml(paths, priorSessionId);
|
|
4843
|
+
const { record } = buildSessionRecord(freshPayload.session, manifest, sessionId, {});
|
|
4844
|
+
const preservedInner = {
|
|
4845
|
+
...record.session,
|
|
4846
|
+
// A human may have linked this imported session to a task
|
|
4847
|
+
// (`basou task link` updates session.yaml.task_id even for imported
|
|
4848
|
+
// sessions); never drop that link on a re-derive.
|
|
4849
|
+
task_id: prior.session.task_id ?? null,
|
|
4850
|
+
// Re-derivation always yields a null summary; keep a prior non-null one.
|
|
4851
|
+
summary: prior.session.summary ?? record.session.summary ?? null
|
|
4852
|
+
};
|
|
4853
|
+
const updatedRecord = { schema_version: "0.1.0", session: preservedInner };
|
|
4854
|
+
if (options.dryRun !== true) {
|
|
4855
|
+
await writeEventsBulk(sessionDir, mergedEvents);
|
|
4856
|
+
try {
|
|
4857
|
+
await overwriteYamlFile(join14(sessionDir, "session.yaml"), updatedRecord);
|
|
4858
|
+
} catch (error) {
|
|
4859
|
+
await writeEventsBulk(sessionDir, priorEvents).catch(() => void 0);
|
|
4860
|
+
throw error;
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
return {
|
|
4864
|
+
status: "reimported",
|
|
4865
|
+
sessionId,
|
|
4866
|
+
eventCount: mergedEvents.length,
|
|
4867
|
+
preservedCount: preserved.length,
|
|
4868
|
+
reusedIdCount
|
|
4869
|
+
};
|
|
4870
|
+
} finally {
|
|
4871
|
+
await lock?.release();
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4725
4874
|
|
|
4726
4875
|
// src/index.ts
|
|
4727
4876
|
var BASOU_CORE_VERSION = "0.1.0";
|
|
@@ -4789,6 +4938,7 @@ export {
|
|
|
4789
4938
|
getDiff,
|
|
4790
4939
|
getSnapshot,
|
|
4791
4940
|
importSessionFromJson,
|
|
4941
|
+
isImportDerivedSource,
|
|
4792
4942
|
isLazyExpired,
|
|
4793
4943
|
isValidPrefixedId,
|
|
4794
4944
|
linkYamlFile,
|
|
@@ -4810,6 +4960,7 @@ export {
|
|
|
4810
4960
|
reconcileAllTasks,
|
|
4811
4961
|
reconcileTask,
|
|
4812
4962
|
refreshTaskLinkedSessions,
|
|
4963
|
+
reimportPreservingId,
|
|
4813
4964
|
renderDecisions,
|
|
4814
4965
|
renderHandoff,
|
|
4815
4966
|
renderWithMarkers,
|