@basou/core 0.28.0 → 0.29.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 +60 -1
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,65 @@ declare function resolveClaudeCodeCommand(lookup?: CommandLookup): Promise<{
|
|
|
45
45
|
*/
|
|
46
46
|
declare function summarizeAdapterOutput(_stream: "stdout" | "stderr", _raw: string): string;
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Pure transforms for registering / removing basou's Stop hook inside a parsed
|
|
50
|
+
* Claude Code settings.json object. No disk or environment access: the CLI reads
|
|
51
|
+
* and writes the file, parses the JSON, and passes the object here so the
|
|
52
|
+
* merge/removal logic stays deterministic and unit-testable.
|
|
53
|
+
*
|
|
54
|
+
* settings.json holds many unrelated keys (permissions, model, other hooks);
|
|
55
|
+
* these functions clone the input and touch ONLY the `hooks.Stop` entry that
|
|
56
|
+
* basou owns, preserving everything else byte-for-byte through the round-trip.
|
|
57
|
+
*/
|
|
58
|
+
/** Seconds before Claude Code kills the hook process. Matches the documented orient (SessionStart) hook. */
|
|
59
|
+
declare const STOP_HOOK_TIMEOUT_SECONDS = 20;
|
|
60
|
+
declare function isBasouStopHookCommand(command: string): boolean;
|
|
61
|
+
type BuildStopHookCommandOptions = {
|
|
62
|
+
/** Absolute path to the CLI entry to invoke (the running dist/index.js). */
|
|
63
|
+
cliEntry: string;
|
|
64
|
+
/** Register the blocking (opt-in enforcement) form. */
|
|
65
|
+
block?: boolean;
|
|
66
|
+
/** Override the file-edit threshold passed to `hook stop`. */
|
|
67
|
+
minEdits?: number;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Build the shell command basou registers as a Stop hook. Uses the node path
|
|
71
|
+
* (not the `basou` alias, which is often absent from a non-interactive hook's
|
|
72
|
+
* PATH) and a `2>/dev/null || true` wrapper so a stale/incorrect dist path or
|
|
73
|
+
* any crash fails open — no per-turn error noise. The wrapper is safe for the
|
|
74
|
+
* blocking form because that emits `decision:"block"` on stdout with exit 0;
|
|
75
|
+
* `|| true` would defeat an exit-2 block but leaves the JSON form intact.
|
|
76
|
+
*
|
|
77
|
+
* The entry path is shell-quoted so a home/project directory containing spaces
|
|
78
|
+
* or shell metacharacters still invokes correctly (an unquoted path with a
|
|
79
|
+
* space would split into the wrong argv and the hook would silently no-op).
|
|
80
|
+
*/
|
|
81
|
+
declare function buildStopHookCommand(options: BuildStopHookCommandOptions): string;
|
|
82
|
+
type ClaudeSettings = Record<string, unknown>;
|
|
83
|
+
type StopHookUpsert = {
|
|
84
|
+
settings: ClaudeSettings;
|
|
85
|
+
/** `installed` = a new entry was appended; `updated` = an existing basou entry was rewritten; `unchanged` = already canonical. */
|
|
86
|
+
action: "installed" | "updated" | "unchanged";
|
|
87
|
+
};
|
|
88
|
+
type StopHookRemoval = {
|
|
89
|
+
settings: ClaudeSettings;
|
|
90
|
+
action: "removed" | "absent";
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Register (or upgrade in place) basou's Stop hook. Idempotent: an existing
|
|
94
|
+
* basou Stop hook is rewritten to the canonical command + timeout; a foreign
|
|
95
|
+
* Stop hook or any other settings key is left untouched.
|
|
96
|
+
*/
|
|
97
|
+
declare function upsertStopHook(settings: unknown, command: string): StopHookUpsert;
|
|
98
|
+
/**
|
|
99
|
+
* Remove every basou-owned Stop hook. A group emptied by the removal is dropped;
|
|
100
|
+
* a now-empty `hooks.Stop` / `hooks` container is deleted so the file does not
|
|
101
|
+
* accumulate empty scaffolding. Foreign hooks and other keys are preserved.
|
|
102
|
+
*/
|
|
103
|
+
declare function removeStopHook(settings: unknown): StopHookRemoval;
|
|
104
|
+
/** Return the installed basou Stop hook command, or null if none is registered. */
|
|
105
|
+
declare function findBasouStopHookCommand(settings: unknown): string | null;
|
|
106
|
+
|
|
48
107
|
/**
|
|
49
108
|
* Schema for `.basou/manifest.yaml`. The minimal manifest carries
|
|
50
109
|
* schema_version, basou_version, workspace metadata, project info, enabled
|
|
@@ -5827,4 +5886,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
|
|
|
5827
5886
|
*/
|
|
5828
5887
|
declare const BASOU_CORE_VERSION = "0.1.0";
|
|
5829
5888
|
|
|
5830
|
-
export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, type ActiveTimeBasis, type AdapterOutputEvent, type AdoptCandidate, type AdoptCandidateKind, type AppendBasouGitignoreOptions, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchivePlan, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type CitedReview, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, type ExistingViewLink, FailedToFinalizeError, type FederatedRoot, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type GitignorePlanSummary, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, type InstructionFileFact, type InstructionSymlinkFact, type InstructionSymlinkState, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type Markers, type MeasureAvailability, type NoteAddedEvent, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, PROTOCOL_END, PROTOCOL_START, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type ProcessRunner, type PublishKind, type PublishTarget, type RechainOptions, type RechainResult, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type RenamePlan, type ReplayOptions, type ReplayWarning, type RepoEntry, type RepoGitignoreFacts, type RepoGitignorePlan, type RepoInstructions, type RepoLanguage, type RepoPresetFacts, type RepoPresetPlan, type RepoSymlinkFacts, type RepoSymlinkPlan, type RepoVisibility, type RepoWiringFacts, type ReportApprovalItem, type ReportData, type ReportDecisionItem, type ReportRendererInput, type ReportRendererResult, type ReportSessionItem, type ReportTaskItem, type RetrofitAction, type RetrofitAgentsState, type RetrofitFacts, type RetrofitPlan, type RetrofitReason, type ReviewGapRepoSummary, type ReviewGapUnit, type ReviewGapVerdict, type ReviewGapsInput, type ReviewGapsSummary, type RiskLevel, RiskLevelSchema, type RosterAdoptionPlan, type RosterDriftSummary, 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 SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceRootScope, type SourceRootsReconcile, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type StopHookEvaluation, type StopHookEvaluationInput, type StopHookSilentReason, type SuspectReason, type SymlinkCollision, type SymlinkConflict, type SymlinkPlanSummary, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, type TaskStatusCount, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type ViewCollision, type ViewConflict, type ViewLinkState, type ViewRepoFact, type ViewStrayUnknown, type WiringRisk, type WiringSummary, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WorkspaceViewPlan, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findErrorCode, findReviewGaps, formatDurationMs, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, instructionMode, isGitNotFound, isImportDerivedSource, isLazyExpired, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseDuration, parseMarkers, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderReport, renderWithMarkers, replayEvents, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|
|
5889
|
+
export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, type ActiveTimeBasis, type AdapterOutputEvent, type AdoptCandidate, type AdoptCandidateKind, type AppendBasouGitignoreOptions, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchivePlan, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, type BuildStopHookCommandOptions, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type CitedReview, type ClaudeSettings, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, type ExistingViewLink, FailedToFinalizeError, type FederatedRoot, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type GitignorePlanSummary, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, type InstructionFileFact, type InstructionSymlinkFact, type InstructionSymlinkState, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type Markers, type MeasureAvailability, type NoteAddedEvent, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, PROTOCOL_END, PROTOCOL_START, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type ProcessRunner, type PublishKind, type PublishTarget, type RechainOptions, type RechainResult, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type RenamePlan, type ReplayOptions, type ReplayWarning, type RepoEntry, type RepoGitignoreFacts, type RepoGitignorePlan, type RepoInstructions, type RepoLanguage, type RepoPresetFacts, type RepoPresetPlan, type RepoSymlinkFacts, type RepoSymlinkPlan, type RepoVisibility, type RepoWiringFacts, type ReportApprovalItem, type ReportData, type ReportDecisionItem, type ReportRendererInput, type ReportRendererResult, type ReportSessionItem, type ReportTaskItem, type RetrofitAction, type RetrofitAgentsState, type RetrofitFacts, type RetrofitPlan, type RetrofitReason, type ReviewGapRepoSummary, type ReviewGapUnit, type ReviewGapVerdict, type ReviewGapsInput, type ReviewGapsSummary, type RiskLevel, RiskLevelSchema, type RosterAdoptionPlan, type RosterDriftSummary, type RunOptions, type RunResult, STOP_HOOK_TIMEOUT_SECONDS, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceRootScope, type SourceRootsReconcile, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type StopHookEvaluation, type StopHookEvaluationInput, type StopHookRemoval, type StopHookSilentReason, type StopHookUpsert, type SuspectReason, type SymlinkCollision, type SymlinkConflict, type SymlinkPlanSummary, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, type TaskStatusCount, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type ViewCollision, type ViewConflict, type ViewLinkState, type ViewRepoFact, type ViewStrayUnknown, type WiringRisk, type WiringSummary, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WorkspaceViewPlan, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, buildStopHookCommand, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouStopHookCommand, findErrorCode, findReviewGaps, formatDurationMs, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, instructionMode, isBasouStopHookCommand, isGitNotFound, isImportDerivedSource, isLazyExpired, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseDuration, parseMarkers, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeStopHook, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderReport, renderWithMarkers, replayEvents, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, upsertStopHook, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,118 @@ function summarizeAdapterOutput(_stream, _raw) {
|
|
|
21
21
|
throw new Error("adapter_output summary is not implemented in this release");
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// src/adapters/claude-code/settings-hook.ts
|
|
25
|
+
var STOP_HOOK_TIMEOUT_SECONDS = 20;
|
|
26
|
+
var BASOU_STOP_HOOK = /(?:\bbasou|(?:@basou|packages)\/cli\/dist\/index\.js['"]?)\s+hook\s+stop\b/;
|
|
27
|
+
function isBasouStopHookCommand(command) {
|
|
28
|
+
return BASOU_STOP_HOOK.test(command);
|
|
29
|
+
}
|
|
30
|
+
function shellQuote(value) {
|
|
31
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
32
|
+
}
|
|
33
|
+
function buildStopHookCommand(options) {
|
|
34
|
+
const flags = [];
|
|
35
|
+
if (options.block === true) flags.push("--block");
|
|
36
|
+
if (options.minEdits !== void 0) flags.push(`--min-edits ${options.minEdits}`);
|
|
37
|
+
const suffix = flags.length > 0 ? ` ${flags.join(" ")}` : "";
|
|
38
|
+
return `node ${shellQuote(options.cliEntry)} hook stop${suffix} 2>/dev/null || true`;
|
|
39
|
+
}
|
|
40
|
+
function isRecord(value) {
|
|
41
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42
|
+
}
|
|
43
|
+
function cloneSettings(settings) {
|
|
44
|
+
if (settings === void 0 || settings === null) return {};
|
|
45
|
+
if (!isRecord(settings)) {
|
|
46
|
+
throw new Error("Claude settings is not a JSON object.");
|
|
47
|
+
}
|
|
48
|
+
return structuredClone(settings);
|
|
49
|
+
}
|
|
50
|
+
function upsertStopHook(settings, command) {
|
|
51
|
+
const root = cloneSettings(settings);
|
|
52
|
+
if (root.hooks === void 0) {
|
|
53
|
+
root.hooks = {};
|
|
54
|
+
} else if (!isRecord(root.hooks)) {
|
|
55
|
+
throw new Error("The 'hooks' key in Claude settings is not an object.");
|
|
56
|
+
}
|
|
57
|
+
const hooks = root.hooks;
|
|
58
|
+
if (hooks.Stop === void 0) {
|
|
59
|
+
hooks.Stop = [];
|
|
60
|
+
} else if (!Array.isArray(hooks.Stop)) {
|
|
61
|
+
throw new Error("The 'hooks.Stop' key in Claude settings is not an array.");
|
|
62
|
+
}
|
|
63
|
+
const stop = hooks.Stop;
|
|
64
|
+
for (const group of stop) {
|
|
65
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) continue;
|
|
66
|
+
for (const entry of group.hooks) {
|
|
67
|
+
if (!isRecord(entry)) continue;
|
|
68
|
+
if (typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
69
|
+
const unchanged = entry.type === "command" && entry.command === command && entry.timeout === STOP_HOOK_TIMEOUT_SECONDS;
|
|
70
|
+
entry.type = "command";
|
|
71
|
+
entry.command = command;
|
|
72
|
+
entry.timeout = STOP_HOOK_TIMEOUT_SECONDS;
|
|
73
|
+
return { settings: root, action: unchanged ? "unchanged" : "updated" };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
stop.push({ hooks: [{ type: "command", command, timeout: STOP_HOOK_TIMEOUT_SECONDS }] });
|
|
78
|
+
return { settings: root, action: "installed" };
|
|
79
|
+
}
|
|
80
|
+
function removeStopHook(settings) {
|
|
81
|
+
const root = cloneSettings(settings);
|
|
82
|
+
if (!isRecord(root.hooks) || !Array.isArray(root.hooks.Stop)) {
|
|
83
|
+
return { settings: root, action: "absent" };
|
|
84
|
+
}
|
|
85
|
+
const hooks = root.hooks;
|
|
86
|
+
const stop = hooks.Stop;
|
|
87
|
+
let removed = false;
|
|
88
|
+
const newStop = [];
|
|
89
|
+
for (const group of stop) {
|
|
90
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) {
|
|
91
|
+
newStop.push(group);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const keptHooks = group.hooks.filter((entry) => {
|
|
95
|
+
if (isRecord(entry) && typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
96
|
+
removed = true;
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
});
|
|
101
|
+
if (keptHooks.length === group.hooks.length) {
|
|
102
|
+
newStop.push(group);
|
|
103
|
+
} else if (keptHooks.length > 0) {
|
|
104
|
+
group.hooks = keptHooks;
|
|
105
|
+
newStop.push(group);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!removed) {
|
|
109
|
+
return { settings: root, action: "absent" };
|
|
110
|
+
}
|
|
111
|
+
if (newStop.length === 0) {
|
|
112
|
+
delete hooks.Stop;
|
|
113
|
+
} else {
|
|
114
|
+
hooks.Stop = newStop;
|
|
115
|
+
}
|
|
116
|
+
if (Object.keys(hooks).length === 0) {
|
|
117
|
+
delete root.hooks;
|
|
118
|
+
}
|
|
119
|
+
return { settings: root, action: "removed" };
|
|
120
|
+
}
|
|
121
|
+
function findBasouStopHookCommand(settings) {
|
|
122
|
+
if (!isRecord(settings) || !isRecord(settings.hooks) || !Array.isArray(settings.hooks.Stop)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
for (const group of settings.hooks.Stop) {
|
|
126
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) continue;
|
|
127
|
+
for (const entry of group.hooks) {
|
|
128
|
+
if (isRecord(entry) && typeof entry.command === "string" && isBasouStopHookCommand(entry.command)) {
|
|
129
|
+
return entry.command;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
24
136
|
// src/adapters/claude-code/ask-user-question.ts
|
|
25
137
|
function readString(value) {
|
|
26
138
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -7664,6 +7776,7 @@ export {
|
|
|
7664
7776
|
PROTOCOL_END,
|
|
7665
7777
|
PROTOCOL_START,
|
|
7666
7778
|
RiskLevelSchema,
|
|
7779
|
+
STOP_HOOK_TIMEOUT_SECONDS,
|
|
7667
7780
|
STUCK_THRESHOLD_MS,
|
|
7668
7781
|
SchemaVersionSchema,
|
|
7669
7782
|
SessionIdSchema,
|
|
@@ -7691,6 +7804,7 @@ export {
|
|
|
7691
7804
|
basouPaths,
|
|
7692
7805
|
buildJsonSchemas,
|
|
7693
7806
|
buildStatusSnapshot,
|
|
7807
|
+
buildStopHookCommand,
|
|
7694
7808
|
chainEvents,
|
|
7695
7809
|
chainRawJsonLines,
|
|
7696
7810
|
classifyFilesBySourceRoot,
|
|
@@ -7712,6 +7826,7 @@ export {
|
|
|
7712
7826
|
enumerateTaskIds,
|
|
7713
7827
|
evaluateStopHook,
|
|
7714
7828
|
finalizeSessionYaml,
|
|
7829
|
+
findBasouStopHookCommand,
|
|
7715
7830
|
findErrorCode,
|
|
7716
7831
|
findReviewGaps,
|
|
7717
7832
|
formatDurationMs,
|
|
@@ -7721,6 +7836,7 @@ export {
|
|
|
7721
7836
|
importSessionFromJson,
|
|
7722
7837
|
inspectChainTail,
|
|
7723
7838
|
instructionMode,
|
|
7839
|
+
isBasouStopHookCommand,
|
|
7724
7840
|
isGitNotFound,
|
|
7725
7841
|
isImportDerivedSource,
|
|
7726
7842
|
isLazyExpired,
|
|
@@ -7759,6 +7875,7 @@ export {
|
|
|
7759
7875
|
refreshTaskLinkedSessions,
|
|
7760
7876
|
reimportPreservingId,
|
|
7761
7877
|
removeMarkerSection,
|
|
7878
|
+
removeStopHook,
|
|
7762
7879
|
renderDecisions,
|
|
7763
7880
|
renderHandoff,
|
|
7764
7881
|
renderOrientation,
|
|
@@ -7788,6 +7905,7 @@ export {
|
|
|
7788
7905
|
ulid,
|
|
7789
7906
|
unknownManifestKeys,
|
|
7790
7907
|
updateTaskStatusWithEvent,
|
|
7908
|
+
upsertStopHook,
|
|
7791
7909
|
verifyEventsChain,
|
|
7792
7910
|
writeEventsBulk,
|
|
7793
7911
|
writeManifest,
|