@gajae-code/coding-agent 0.18.11 → 0.18.12
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/CHANGELOG.md +293 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +1 -0
- package/dist/types/cli/update-cli.d.ts +14 -1
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +5 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/config/autorouting-tier-map.d.ts +30 -0
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +39 -0
- package/dist/types/config/file-lock.d.ts +8 -1
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -6
- package/dist/types/config/model-registry.d.ts +56 -5
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +46 -3
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/modes/patch.d.ts +5 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +10 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/types.d.ts +15 -3
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
- package/dist/types/sdk/broker/broker.d.ts +7 -1
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +136 -7
- package/dist/types/sdk/broker/hop.d.ts +36 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +4 -1
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +23 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.d.ts +32 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +58 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +13 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
- package/dist/types/tools/descriptors.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +8 -8
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +22 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +27 -19
- package/src/capability/index.ts +2 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +7 -5
- package/src/cli/public-command-errors.ts +4 -0
- package/src/cli/root-flags.ts +2 -2
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +224 -7
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +199 -42
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/message.ts +10 -3
- package/src/config/autorouting-tier-map.ts +30 -0
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +734 -0
- package/src/config/file-lock.ts +216 -56
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +716 -113
- package/src/config/model-registry.ts +1334 -158
- package/src/config/model-resolver.ts +3 -1
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +60 -3
- package/src/config/settings.ts +458 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/crash/sanitize.ts +4 -0
- package/src/customization/import.ts +3 -1
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/debug/crash-diagnostics.ts +2 -1
- package/src/debug/report-bundle.ts +19 -0
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/helpers.ts +1 -2
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +13 -17
- package/src/edit/modes/patch.ts +187 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/export/html/index.ts +46 -6
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +8 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/gjc-runtime/gc-runtime.ts +33 -6
- package/src/gjc-runtime/launch-tmux.ts +7 -2
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/hooks/native-skill-hook.ts +14 -11
- package/src/internal-urls/docs-index.generated.ts +14 -13
- package/src/internal-urls/local-protocol.ts +142 -8
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/migrate/action-planner.ts +57 -0
- package/src/migrate/adapters/claude-code.ts +23 -4
- package/src/migrate/adapters/codex.ts +22 -4
- package/src/migrate/adapters/index.ts +22 -4
- package/src/migrate/adapters/opencode.ts +6 -1
- package/src/migrate/executor.ts +84 -7
- package/src/migrate/report.ts +19 -2
- package/src/migrate/types.ts +14 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/controllers/command-controller.ts +38 -2
- package/src/modes/controllers/plan-mode-controller.ts +17 -7
- package/src/modes/controllers/selector-controller.ts +62 -6
- package/src/modes/interactive-mode.ts +68 -0
- package/src/modes/theme/theme.ts +15 -0
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +32 -0
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +126 -17
- package/src/sdk/broker/broker-exit.ts +8 -5
- package/src/sdk/broker/broker.ts +342 -82
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1143 -265
- package/src/sdk/broker/hop.ts +274 -0
- package/src/sdk/broker/lifecycle-ledger.ts +35 -11
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +62 -12
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/index.ts +52 -21
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/cli/session-cli.ts +21 -6
- package/src/sdk/host/session-runtime.test.ts +118 -23
- package/src/sdk/host/session-runtime.ts +352 -47
- package/src/sdk/lifecycle/service.ts +1 -0
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/protocol/adapter-validation.ts +53 -11
- package/src/sdk/protocol/operation-inventory.generated.json +101 -2
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +114 -61
- package/src/session/agent-session.ts +1043 -81
- package/src/session/internal/managed-session-scope.ts +126 -39
- package/src/session/internal/managed-session-storage.ts +14 -11
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +236 -14
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +491 -32
- package/src/slash-commands/builtin-registry.ts +15 -3
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/task/executor.ts +103 -12
- package/src/task/index.ts +389 -175
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +3 -0
- package/src/tools/bash-allowed-prefixes.ts +153 -5
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash.ts +14 -0
- package/src/tools/debug.ts +7 -6
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +34 -2
- package/src/tools/fetch.ts +3 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/output-meta.ts +23 -2
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +17 -35
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +108 -1
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +31 -3
- package/src/tools/write.ts +35 -3
- package/src/utils/commit-message-generator.ts +9 -2
- package/src/utils/file-mentions.ts +29 -1
- package/src/utils/title-generator.ts +7 -2
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
|
@@ -299,6 +299,7 @@ export type ManagedScopeErrorCode =
|
|
|
299
299
|
| "managed_gc_journal_capacity_exceeded"
|
|
300
300
|
| "atomic_unavailable"
|
|
301
301
|
| "invalid_request"
|
|
302
|
+
| "permission_denied"
|
|
302
303
|
| "durability_failed"
|
|
303
304
|
| "durability_not_provable"
|
|
304
305
|
| "capacity_exceeded";
|
|
@@ -342,6 +343,7 @@ const managedScopeErrnoFailureCodes = new Set([
|
|
|
342
343
|
const managedScopeFailureCodes = new Set<ManagedScopeErrorCode>([
|
|
343
344
|
"atomic_unavailable",
|
|
344
345
|
"invalid_request",
|
|
346
|
+
"permission_denied",
|
|
345
347
|
"durability_failed",
|
|
346
348
|
"durability_not_provable",
|
|
347
349
|
"migration_busy",
|
|
@@ -441,6 +443,7 @@ export type ManagedOpenFailure =
|
|
|
441
443
|
| "managed_gc_journal_capacity_exceeded"
|
|
442
444
|
| "durability_failed"
|
|
443
445
|
| "atomic_unavailable"
|
|
446
|
+
| "permission_denied"
|
|
444
447
|
| "invalid_request"
|
|
445
448
|
| "durability_not_provable"
|
|
446
449
|
| "migration_retired"
|
|
@@ -1166,7 +1169,8 @@ function listDirectoryCandidates(
|
|
|
1166
1169
|
try {
|
|
1167
1170
|
directoryStat = fs.lstatSync(directory);
|
|
1168
1171
|
} catch (error) {
|
|
1169
|
-
|
|
1172
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
1173
|
+
if (code === "ENOENT" || (provenance === "legacy" && code === "ENAMETOOLONG")) return [];
|
|
1170
1174
|
throw error;
|
|
1171
1175
|
}
|
|
1172
1176
|
if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) throw new Error("unsafe directory");
|
|
@@ -1970,7 +1974,8 @@ export function listManagedCandidates(scope: ManagedScope): ManagedCandidateList
|
|
|
1970
1974
|
}
|
|
1971
1975
|
}
|
|
1972
1976
|
}
|
|
1973
|
-
const
|
|
1977
|
+
const retired = owned.length > 0 ? retiredTargetKeys(scope) : new Set<string>();
|
|
1978
|
+
const visible = owned.filter(candidate => !isRetiredIn(retired, candidate));
|
|
1974
1979
|
const active = visible.filter(
|
|
1975
1980
|
candidate =>
|
|
1976
1981
|
candidate.provenance === "v2" ||
|
|
@@ -2041,6 +2046,7 @@ function expectedFailure(error: unknown): ManagedOpenFailure {
|
|
|
2041
2046
|
message === "managed_gc_journal_capacity_exceeded" ||
|
|
2042
2047
|
message === "durability_failed" ||
|
|
2043
2048
|
message === "atomic_unavailable" ||
|
|
2049
|
+
message === "permission_denied" ||
|
|
2044
2050
|
message === "invalid_request" ||
|
|
2045
2051
|
message === "durability_not_provable" ||
|
|
2046
2052
|
message === "migration_retired"
|
|
@@ -2692,11 +2698,14 @@ function managedGcStreamDirectoryInventory(
|
|
|
2692
2698
|
countEntry: (entry: fs.Dirent) => boolean,
|
|
2693
2699
|
retain: (entry: fs.Dirent) => boolean,
|
|
2694
2700
|
operation: ManagedGcInventoryOperation,
|
|
2701
|
+
verificationBaseline?: ManagedGcDirectoryInventory,
|
|
2695
2702
|
): ManagedGcDirectoryInventory {
|
|
2696
2703
|
managedGcReserveInventoryWork(operation);
|
|
2697
2704
|
const beforeStat = fs.lstatSync(pathname, { bigint: true });
|
|
2698
2705
|
if (!beforeStat.isDirectory() || beforeStat.isSymbolicLink()) throw new Error("managed_gc_scope_authority_mismatch");
|
|
2699
2706
|
const before = managedGcDirectoryEvidence(beforeStat);
|
|
2707
|
+
if (verificationBaseline && !managedGcSameDirectoryEvidence(before, verificationBaseline.evidence))
|
|
2708
|
+
throw new Error("managed_gc_scope_authority_mismatch");
|
|
2700
2709
|
const scan = (collect: boolean): { count: number; physicalEntryCount: number; entries: fs.Dirent[] } => {
|
|
2701
2710
|
managedGcReserveInventoryWork(operation);
|
|
2702
2711
|
const entries: fs.Dirent[] = [];
|
|
@@ -2742,7 +2751,9 @@ function managedGcStreamDirectoryInventory(
|
|
|
2742
2751
|
managedGcReserveInventoryWork(operation);
|
|
2743
2752
|
return { count, physicalEntryCount, entries };
|
|
2744
2753
|
};
|
|
2745
|
-
const counted =
|
|
2754
|
+
const counted = verificationBaseline
|
|
2755
|
+
? { count: verificationBaseline.entryCount, physicalEntryCount: verificationBaseline.physicalEntryCount }
|
|
2756
|
+
: scan(false);
|
|
2746
2757
|
managedGcReserveInventoryWork(operation);
|
|
2747
2758
|
const afterCount = fs.lstatSync(pathname, { bigint: true });
|
|
2748
2759
|
if (
|
|
@@ -2776,6 +2787,7 @@ function managedGcReceiptDirectoryInventory(
|
|
|
2776
2787
|
scope: ManagedScope,
|
|
2777
2788
|
store: ManagedSessionDescendantStore,
|
|
2778
2789
|
operation: ManagedGcInventoryOperation,
|
|
2790
|
+
verificationBaseline?: ManagedGcDirectoryInventory,
|
|
2779
2791
|
): ManagedGcDirectoryInventory {
|
|
2780
2792
|
const relativePath = MANAGED_GC_RETIREMENT_RECEIPTS;
|
|
2781
2793
|
managedGcReserveInventoryWork(
|
|
@@ -2789,6 +2801,7 @@ function managedGcReceiptDirectoryInventory(
|
|
|
2789
2801
|
entry => entry.name.startsWith(MANAGED_GC_RETIREMENT_PREFIX),
|
|
2790
2802
|
entry => entry.name.startsWith(MANAGED_GC_RETIREMENT_PREFIX),
|
|
2791
2803
|
operation,
|
|
2804
|
+
verificationBaseline,
|
|
2792
2805
|
);
|
|
2793
2806
|
managedGcReserveInventoryWork(operation);
|
|
2794
2807
|
const after = store.captureDirectoryIdentity(relativePath);
|
|
@@ -3606,14 +3619,20 @@ export async function readManagedGcSessionRetirementReceiptReadOnly(
|
|
|
3606
3619
|
if (!hasFsCode(error, "ENOENT")) throw error;
|
|
3607
3620
|
receiptDirectoryPresent = false;
|
|
3608
3621
|
}
|
|
3609
|
-
if (receiptDirectoryPresent)
|
|
3622
|
+
if (receiptDirectoryPresent) {
|
|
3623
|
+
const inventory = managedGcReceiptDirectoryInventory(scope, store, operation);
|
|
3610
3624
|
receipt = readManagedGcSessionRetirementReceiptUnlocked(
|
|
3611
3625
|
scope,
|
|
3612
3626
|
transcriptPath,
|
|
3613
3627
|
trusted,
|
|
3614
3628
|
store,
|
|
3615
3629
|
operation,
|
|
3630
|
+
inventory,
|
|
3616
3631
|
).receipt;
|
|
3632
|
+
const after = managedGcReceiptDirectoryInventory(scope, store, operation, inventory);
|
|
3633
|
+
if (!managedGcSameReceiptDirectoryInventory(inventory, after))
|
|
3634
|
+
throw new Error("task_artifact_owner_continuation_authority_mismatch");
|
|
3635
|
+
}
|
|
3617
3636
|
} catch (error) {
|
|
3618
3637
|
primaryError = error;
|
|
3619
3638
|
hasPrimaryError = true;
|
|
@@ -6282,8 +6301,96 @@ function tombstonePathContaining(scope: ManagedScope, candidate: ManagedCandidat
|
|
|
6282
6301
|
return undefined;
|
|
6283
6302
|
}
|
|
6284
6303
|
|
|
6285
|
-
|
|
6304
|
+
/**
|
|
6305
|
+
* Identity fields a retired tombstone target must match exactly for a candidate
|
|
6306
|
+
* to be hidden. `dev`, `ino`, and `mtimeNs` are persisted as decimal strings.
|
|
6307
|
+
*/
|
|
6308
|
+
type RetiredTargetIdentity = readonly [
|
|
6309
|
+
path: string,
|
|
6310
|
+
sessionId: string,
|
|
6311
|
+
cwd: string,
|
|
6312
|
+
canonicalPath: string,
|
|
6313
|
+
dev: string,
|
|
6314
|
+
ino: string,
|
|
6315
|
+
size: number,
|
|
6316
|
+
mtimeNs: string,
|
|
6317
|
+
sha256: string,
|
|
6318
|
+
];
|
|
6319
|
+
|
|
6320
|
+
function candidateRetiredIdentity(candidate: ManagedCandidate): RetiredTargetIdentity {
|
|
6321
|
+
return [
|
|
6322
|
+
candidate.path,
|
|
6323
|
+
candidate.sessionId,
|
|
6324
|
+
candidate.cwd,
|
|
6325
|
+
candidate.identity.canonicalPath,
|
|
6326
|
+
String(candidate.identity.dev),
|
|
6327
|
+
String(candidate.identity.ino),
|
|
6328
|
+
candidate.identity.size,
|
|
6329
|
+
String(candidate.identity.mtimeNs),
|
|
6330
|
+
candidate.identity.sha256,
|
|
6331
|
+
];
|
|
6332
|
+
}
|
|
6333
|
+
|
|
6334
|
+
/** Returns the target's identity only when every field has the type a candidate can carry. */
|
|
6335
|
+
function parseRetiredTargetIdentity(target: unknown): RetiredTargetIdentity | undefined {
|
|
6336
|
+
if (!target || typeof target !== "object") return undefined;
|
|
6337
|
+
const value = target as { path?: unknown; sessionId?: unknown; cwd?: unknown; identity?: unknown };
|
|
6338
|
+
if (!value.identity || typeof value.identity !== "object") return undefined;
|
|
6339
|
+
const identity = value.identity as {
|
|
6340
|
+
canonicalPath?: unknown;
|
|
6341
|
+
dev?: unknown;
|
|
6342
|
+
ino?: unknown;
|
|
6343
|
+
size?: unknown;
|
|
6344
|
+
mtimeNs?: unknown;
|
|
6345
|
+
sha256?: unknown;
|
|
6346
|
+
};
|
|
6347
|
+
if (
|
|
6348
|
+
typeof value.path !== "string" ||
|
|
6349
|
+
typeof value.sessionId !== "string" ||
|
|
6350
|
+
typeof value.cwd !== "string" ||
|
|
6351
|
+
typeof identity.canonicalPath !== "string" ||
|
|
6352
|
+
typeof identity.dev !== "string" ||
|
|
6353
|
+
typeof identity.ino !== "string" ||
|
|
6354
|
+
typeof identity.size !== "number" ||
|
|
6355
|
+
typeof identity.mtimeNs !== "string" ||
|
|
6356
|
+
typeof identity.sha256 !== "string"
|
|
6357
|
+
)
|
|
6358
|
+
return undefined;
|
|
6359
|
+
return [
|
|
6360
|
+
value.path,
|
|
6361
|
+
value.sessionId,
|
|
6362
|
+
value.cwd,
|
|
6363
|
+
identity.canonicalPath,
|
|
6364
|
+
identity.dev,
|
|
6365
|
+
identity.ino,
|
|
6366
|
+
identity.size,
|
|
6367
|
+
identity.mtimeNs,
|
|
6368
|
+
identity.sha256,
|
|
6369
|
+
];
|
|
6370
|
+
}
|
|
6371
|
+
|
|
6372
|
+
/**
|
|
6373
|
+
* Key equality matches strict equality of every member: strings and finite
|
|
6374
|
+
* numbers encode distinctly. A non-finite tombstone `size` encodes as `null`,
|
|
6375
|
+
* which no candidate produces.
|
|
6376
|
+
*/
|
|
6377
|
+
function retiredIdentityKey(identity: RetiredTargetIdentity): string {
|
|
6378
|
+
return JSON.stringify(identity);
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6381
|
+
/**
|
|
6382
|
+
* Snapshot of the identities retired by a scope's tombstones.
|
|
6383
|
+
*
|
|
6384
|
+
* Tombstones are visited in directory order and the walk stops at the first
|
|
6385
|
+
* unreadable or malformed one: it grants no retirement authority, and neither do
|
|
6386
|
+
* the tombstones after it. Listing builds this once and checks every candidate
|
|
6387
|
+
* against it, so its cost is linear in tombstones rather than in
|
|
6388
|
+
* candidates x tombstones.
|
|
6389
|
+
*/
|
|
6390
|
+
function retiredTargetKeys(scope: ManagedScope): ReadonlySet<string> {
|
|
6391
|
+
const keys = new Set<string>();
|
|
6286
6392
|
const directory = path.join(managedInternalDirectory(scope), MANAGED_TOMBSTONES_DIRECTORY);
|
|
6393
|
+
const digest = scopeDigest(scope.platform, scope.canonicalCwd);
|
|
6287
6394
|
try {
|
|
6288
6395
|
for (const name of fs.readdirSync(directory)) {
|
|
6289
6396
|
const pathname = path.join(directory, name);
|
|
@@ -6293,47 +6400,27 @@ function isRetired(scope: ManagedScope, candidate: ManagedCandidate): boolean {
|
|
|
6293
6400
|
if (
|
|
6294
6401
|
record.schemaVersion !== 2 ||
|
|
6295
6402
|
record.state !== "retired" ||
|
|
6296
|
-
record.scope !==
|
|
6403
|
+
record.scope !== digest ||
|
|
6297
6404
|
!Array.isArray(record.targets)
|
|
6298
6405
|
)
|
|
6299
6406
|
continue;
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
path?: unknown;
|
|
6305
|
-
sessionId?: unknown;
|
|
6306
|
-
cwd?: unknown;
|
|
6307
|
-
identity?: {
|
|
6308
|
-
canonicalPath?: unknown;
|
|
6309
|
-
dev?: unknown;
|
|
6310
|
-
ino?: unknown;
|
|
6311
|
-
size?: unknown;
|
|
6312
|
-
mtimeNs?: unknown;
|
|
6313
|
-
sha256?: unknown;
|
|
6314
|
-
};
|
|
6315
|
-
};
|
|
6316
|
-
const identity = value.identity;
|
|
6317
|
-
if (!identity) return false;
|
|
6318
|
-
return (
|
|
6319
|
-
value.path === candidate.path &&
|
|
6320
|
-
value.sessionId === candidate.sessionId &&
|
|
6321
|
-
value.cwd === candidate.cwd &&
|
|
6322
|
-
identity.canonicalPath === candidate.identity.canonicalPath &&
|
|
6323
|
-
identity.dev === String(candidate.identity.dev) &&
|
|
6324
|
-
identity.ino === String(candidate.identity.ino) &&
|
|
6325
|
-
identity.size === candidate.identity.size &&
|
|
6326
|
-
identity.mtimeNs === String(candidate.identity.mtimeNs) &&
|
|
6327
|
-
identity.sha256 === candidate.identity.sha256
|
|
6328
|
-
);
|
|
6329
|
-
})
|
|
6330
|
-
)
|
|
6331
|
-
return true;
|
|
6407
|
+
for (const target of record.targets) {
|
|
6408
|
+
const identity = parseRetiredTargetIdentity(target);
|
|
6409
|
+
if (identity) keys.add(retiredIdentityKey(identity));
|
|
6410
|
+
}
|
|
6332
6411
|
}
|
|
6333
6412
|
} catch {
|
|
6334
6413
|
/* a missing/malformed tombstone grants no retirement authority */
|
|
6335
6414
|
}
|
|
6336
|
-
return
|
|
6415
|
+
return keys;
|
|
6416
|
+
}
|
|
6417
|
+
|
|
6418
|
+
function isRetiredIn(retired: ReadonlySet<string>, candidate: ManagedCandidate): boolean {
|
|
6419
|
+
return retired.has(retiredIdentityKey(candidateRetiredIdentity(candidate)));
|
|
6420
|
+
}
|
|
6421
|
+
|
|
6422
|
+
function isRetired(scope: ManagedScope, candidate: ManagedCandidate): boolean {
|
|
6423
|
+
return isRetiredIn(retiredTargetKeys(scope), candidate);
|
|
6337
6424
|
}
|
|
6338
6425
|
|
|
6339
6426
|
type ArtifactManifestEntry =
|
|
@@ -80,6 +80,7 @@ export class ManagedPublishError extends Error {
|
|
|
80
80
|
| "invalid_request"
|
|
81
81
|
| "durability_not_provable"
|
|
82
82
|
| "identity_mismatch"
|
|
83
|
+
| "permission_denied"
|
|
83
84
|
| "io_error"
|
|
84
85
|
| "durability_failed";
|
|
85
86
|
readonly diagnostic: string;
|
|
@@ -141,17 +142,19 @@ function publishFailure(outcome: NativePublishOutcome): ManagedPublishError {
|
|
|
141
142
|
const classification =
|
|
142
143
|
outcome.reason === "destination_exists"
|
|
143
144
|
? "destination_conflict"
|
|
144
|
-
: outcome.reason === "
|
|
145
|
-
? "
|
|
146
|
-
: outcome.reason === "
|
|
147
|
-
? "
|
|
148
|
-
: outcome.reason === "
|
|
149
|
-
? "
|
|
150
|
-
: outcome.reason === "
|
|
151
|
-
? "
|
|
152
|
-
: outcome.reason === "
|
|
153
|
-
? "
|
|
154
|
-
: "
|
|
145
|
+
: outcome.reason === "access_denied" || outcome.reason === "permission_denied"
|
|
146
|
+
? "permission_denied"
|
|
147
|
+
: outcome.reason === "atomic_unavailable"
|
|
148
|
+
? "atomic_unavailable"
|
|
149
|
+
: outcome.reason === "invalid_request"
|
|
150
|
+
? "invalid_request"
|
|
151
|
+
: outcome.reason === "durability_not_provable"
|
|
152
|
+
? "durability_not_provable"
|
|
153
|
+
: outcome.reason === "identity_violation"
|
|
154
|
+
? "identity_mismatch"
|
|
155
|
+
: outcome.reason === "io_failure"
|
|
156
|
+
? "io_error"
|
|
157
|
+
: "durability_failed";
|
|
155
158
|
return new ManagedPublishError(classification, outcome);
|
|
156
159
|
}
|
|
157
160
|
|
|
@@ -6,6 +6,7 @@ export type NativePublishReason =
|
|
|
6
6
|
| "atomic_unavailable"
|
|
7
7
|
| "cross_device"
|
|
8
8
|
| "permission_denied"
|
|
9
|
+
| "access_denied"
|
|
9
10
|
| "io_failure"
|
|
10
11
|
| "interrupted"
|
|
11
12
|
| "invalid_request"
|
|
@@ -77,6 +78,7 @@ const reasons = new Set<NativePublishReason>([
|
|
|
77
78
|
"atomic_unavailable",
|
|
78
79
|
"cross_device",
|
|
79
80
|
"permission_denied",
|
|
81
|
+
"access_denied",
|
|
80
82
|
"io_failure",
|
|
81
83
|
"interrupted",
|
|
82
84
|
"invalid_request",
|
|
@@ -109,6 +111,7 @@ const preMutationReasons = new Set<NativePublishReason>([
|
|
|
109
111
|
"atomic_unavailable",
|
|
110
112
|
"cross_device",
|
|
111
113
|
"permission_denied",
|
|
114
|
+
"access_denied",
|
|
112
115
|
"io_failure",
|
|
113
116
|
"interrupted",
|
|
114
117
|
"invalid_request",
|
|
@@ -184,11 +187,12 @@ function legalOutcome(outcome: NativePublishOutcome): boolean {
|
|
|
184
187
|
"atomic_unavailable",
|
|
185
188
|
"cross_device",
|
|
186
189
|
"permission_denied",
|
|
190
|
+
"access_denied",
|
|
187
191
|
"io_failure",
|
|
188
192
|
"interrupted",
|
|
189
193
|
].includes(outcome.reason)) ||
|
|
190
194
|
(outcome.phase === "preflight" &&
|
|
191
|
-
!["atomic_unavailable", "cross_device", "interrupted"].includes(outcome.reason)) ||
|
|
195
|
+
!["atomic_unavailable", "cross_device", "interrupted", "access_denied"].includes(outcome.reason)) ||
|
|
192
196
|
(outcome.phase === "file_sync" && outcome.reason === "io_failure"))
|
|
193
197
|
);
|
|
194
198
|
if (outcome.mutationState === "unknown")
|
package/src/session/messages.ts
CHANGED
|
@@ -158,6 +158,34 @@ function getPrunedToolResultContent(message: ToolResultMessage): (TextContent |
|
|
|
158
158
|
export const PRE_ADMISSION_ARTIFACT_SPILL_HEAD_BYTES = 4096;
|
|
159
159
|
export const PRE_ADMISSION_ARTIFACT_SPILL_TAIL_BYTES = 4096;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Keep an authenticated `#GJC1_` placeholder whole when the byte cut lands
|
|
163
|
+
* inside it. Short inputs whose head and tail already overlap stay on the
|
|
164
|
+
* original byte limits.
|
|
165
|
+
*/
|
|
166
|
+
function retainStraddlingPlaceholders(text: string, head: string, tail: string): { head: string; tail: string } {
|
|
167
|
+
const headEnd = head.length;
|
|
168
|
+
const tailStart = text.length - tail.length;
|
|
169
|
+
if (headEnd > tailStart) return { head, tail };
|
|
170
|
+
|
|
171
|
+
let nextHeadEnd = headEnd;
|
|
172
|
+
let nextTailStart = tailStart;
|
|
173
|
+
const placeholder = /#GJC1_[A-Za-z0-9_-]{22}#/g;
|
|
174
|
+
for (;;) {
|
|
175
|
+
const match = placeholder.exec(text);
|
|
176
|
+
if (match === null) break;
|
|
177
|
+
const start = match.index;
|
|
178
|
+
const stop = start + match[0].length;
|
|
179
|
+
if (start < headEnd && stop > headEnd) nextHeadEnd = Math.max(nextHeadEnd, stop);
|
|
180
|
+
if (start < tailStart && stop > tailStart) nextTailStart = Math.min(nextTailStart, start);
|
|
181
|
+
}
|
|
182
|
+
if (nextHeadEnd > nextTailStart) return { head, tail };
|
|
183
|
+
return {
|
|
184
|
+
head: nextHeadEnd === headEnd ? head : text.slice(0, nextHeadEnd),
|
|
185
|
+
tail: nextTailStart === tailStart ? tail : text.slice(nextTailStart),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
161
189
|
function utf8Prefix(text: string, maxBytes: number): string {
|
|
162
190
|
if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
|
|
163
191
|
let bytes = 0;
|
|
@@ -193,15 +221,28 @@ function utf8Suffix(text: string, maxBytes: number): string {
|
|
|
193
221
|
* Build the deterministic inline receipt for a tool result saved before the
|
|
194
222
|
* next provider context is constructed. Byte boundaries never split UTF-8
|
|
195
223
|
* code points, so head/tail recovery remains readable for emoji and CJK text.
|
|
224
|
+
*
|
|
225
|
+
* `redact` runs on the complete text before the cut. The digest stays the
|
|
226
|
+
* caller's hash of the stored artifact; the omitted count is the redacted
|
|
227
|
+
* preview's omitted bytes.
|
|
196
228
|
*/
|
|
197
|
-
export function createPreAdmissionArtifactSpillPreview(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
229
|
+
export function createPreAdmissionArtifactSpillPreview(
|
|
230
|
+
fullText: string,
|
|
231
|
+
artifactId: string,
|
|
232
|
+
digest: string,
|
|
233
|
+
redact?: (text: string) => string,
|
|
234
|
+
): string {
|
|
235
|
+
const source = redact ? redact(fullText) : fullText;
|
|
236
|
+
const totalBytes = Buffer.byteLength(source, "utf-8");
|
|
237
|
+
const head = utf8Prefix(source, PRE_ADMISSION_ARTIFACT_SPILL_HEAD_BYTES);
|
|
238
|
+
const tail = utf8Suffix(source, PRE_ADMISSION_ARTIFACT_SPILL_TAIL_BYTES);
|
|
239
|
+
// Without redaction the cut stays on the historical byte limits, including
|
|
240
|
+
// when the tool text itself contains a placeholder-shaped string.
|
|
241
|
+
const retained = redact ? retainStraddlingPlaceholders(source, head, tail) : { head, tail };
|
|
242
|
+
const retainedBytes = Buffer.byteLength(retained.head, "utf-8") + Buffer.byteLength(retained.tail, "utf-8");
|
|
202
243
|
const omittedBytes = Math.max(0, totalBytes - retainedBytes);
|
|
203
244
|
const receipt = `[${omittedBytes} bytes omitted; sha256:${digest}; full output: artifact://${artifactId}]`;
|
|
204
|
-
return `${head}\n\n${receipt}\n\n${tail}`;
|
|
245
|
+
return `${retained.head}\n\n${receipt}\n\n${retained.tail}`;
|
|
205
246
|
}
|
|
206
247
|
|
|
207
248
|
/**
|