@animalabs/agent-framework 0.29.0 → 0.31.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/README.md +71 -8
- package/dist/src/admission/admit.d.ts +90 -0
- package/dist/src/admission/admit.d.ts.map +1 -0
- package/dist/src/admission/admit.js +43 -0
- package/dist/src/admission/admit.js.map +1 -0
- package/dist/src/agent.d.ts +50 -9
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +125 -23
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts.map +1 -1
- package/dist/src/api/mcp-server-core.js +10 -3
- package/dist/src/api/mcp-server-core.js.map +1 -1
- package/dist/src/author-presentation.d.ts +50 -0
- package/dist/src/author-presentation.d.ts.map +1 -0
- package/dist/src/author-presentation.js +58 -0
- package/dist/src/author-presentation.js.map +1 -0
- package/dist/src/code-execution/isolate/render.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/render.js +7 -6
- package/dist/src/code-execution/isolate/render.js.map +1 -1
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +5 -4
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/dendrite/index.d.ts +6 -0
- package/dist/src/dendrite/index.d.ts.map +1 -0
- package/dist/src/dendrite/index.js +3 -0
- package/dist/src/dendrite/index.js.map +1 -0
- package/dist/src/dendrite/presets.d.ts +60 -0
- package/dist/src/dendrite/presets.d.ts.map +1 -0
- package/dist/src/dendrite/presets.js +117 -0
- package/dist/src/dendrite/presets.js.map +1 -0
- package/dist/src/dendrite/registry.d.ts +260 -0
- package/dist/src/dendrite/registry.d.ts.map +1 -0
- package/dist/src/dendrite/registry.js +742 -0
- package/dist/src/dendrite/registry.js.map +1 -0
- package/dist/src/dendrite/types.d.ts +392 -0
- package/dist/src/dendrite/types.d.ts.map +1 -0
- package/dist/src/dendrite/types.js +24 -0
- package/dist/src/dendrite/types.js.map +1 -0
- package/dist/src/framework.d.ts +806 -118
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +4180 -1121
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +36 -21
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +223 -149
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/recipe-reconcile.d.ts.map +1 -1
- package/dist/src/gate/recipe-reconcile.js +6 -5
- package/dist/src/gate/recipe-reconcile.js.map +1 -1
- package/dist/src/host-presentation.d.ts +4 -0
- package/dist/src/host-presentation.d.ts.map +1 -1
- package/dist/src/host-presentation.js +12 -10
- package/dist/src/host-presentation.js.map +1 -1
- package/dist/src/index.d.ts +6 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/inference-bounds.d.ts +37 -0
- package/dist/src/inference-bounds.d.ts.map +1 -0
- package/dist/src/inference-bounds.js +84 -0
- package/dist/src/inference-bounds.js.map +1 -0
- package/dist/src/line-reader.d.ts +7 -1
- package/dist/src/line-reader.d.ts.map +1 -1
- package/dist/src/line-reader.js +17 -6
- package/dist/src/line-reader.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +84 -9
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +136 -58
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/errors.d.ts +1 -0
- package/dist/src/mcpl/errors.d.ts.map +1 -1
- package/dist/src/mcpl/errors.js +3 -0
- package/dist/src/mcpl/errors.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +2 -2
- package/dist/src/mcpl/inbound-source.js +2 -2
- package/dist/src/mcpl/inference-router.d.ts +11 -1
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +65 -9
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +10 -7
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
- package/dist/src/mcpl/modern-connection.js +85 -74
- package/dist/src/mcpl/modern-connection.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts +1 -1
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +45 -3
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +11 -7
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +21 -0
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +1 -2
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +3 -3
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +14 -0
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +26 -22
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-signature.d.ts +1 -0
- package/dist/src/mcpl/tool-signature.d.ts.map +1 -1
- package/dist/src/mcpl/tool-signature.js +16 -11
- package/dist/src/mcpl/tool-signature.js.map +1 -1
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
- package/dist/src/mcpl/toolsets-module.js +7 -0
- package/dist/src/mcpl/toolsets-module.js.map +1 -1
- package/dist/src/mcpl/transport.d.ts +44 -21
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +283 -64
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +17 -1
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/module-registry.d.ts +32 -4
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +189 -25
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.js +24 -16
- package/dist/src/modules/discord/discord-js-client.js.map +1 -1
- package/dist/src/modules/sender-name.d.ts +5 -4
- package/dist/src/modules/sender-name.d.ts.map +1 -1
- package/dist/src/modules/sender-name.js +7 -5
- package/dist/src/modules/sender-name.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +16 -8
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +33 -12
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +6 -3
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +61 -15
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +9 -1
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +50 -10
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts +11 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +19 -8
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +8 -0
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +7 -0
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +7 -5
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/notice-tags.d.ts +2 -0
- package/dist/src/notice-tags.d.ts.map +1 -1
- package/dist/src/notice-tags.js +2 -0
- package/dist/src/notice-tags.js.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.js +1 -9
- package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
- package/dist/src/silent-heartbeat.d.ts +4 -2
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js +7 -4
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/stored-injections.d.ts +4 -0
- package/dist/src/stored-injections.d.ts.map +1 -1
- package/dist/src/stored-injections.js +6 -0
- package/dist/src/stored-injections.js.map +1 -1
- package/dist/src/supplied-text.d.ts +2 -0
- package/dist/src/supplied-text.d.ts.map +1 -1
- package/dist/src/supplied-text.js +16 -7
- package/dist/src/supplied-text.js.map +1 -1
- package/dist/src/tool-result-guard.js +1 -1
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +368 -16
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +1224 -136
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +115 -7
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/tune-out/tools.js +55 -18
- package/dist/src/tune-out/tools.js.map +1 -1
- package/dist/src/types/agent.d.ts +27 -1
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +153 -15
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +42 -3
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +140 -3
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/admission/admit.ts +113 -0
- package/src/agent.ts +138 -31
- package/src/api/mcp-server-core.ts +10 -3
- package/src/author-presentation.ts +81 -0
- package/src/code-execution/isolate/render.ts +7 -6
- package/src/code-execution/isolate/scripts.ts +5 -4
- package/src/dendrite/index.ts +32 -0
- package/src/dendrite/presets.ts +149 -0
- package/src/dendrite/registry.ts +808 -0
- package/src/dendrite/types.ts +397 -0
- package/src/framework.ts +4344 -1052
- package/src/gate/event-gate.ts +251 -150
- package/src/gate/recipe-reconcile.ts +7 -5
- package/src/host-presentation.ts +14 -10
- package/src/index.ts +16 -2
- package/src/inference-bounds.ts +111 -0
- package/src/line-reader.ts +22 -5
- package/src/mcpl/channel-registry.ts +170 -60
- package/src/mcpl/errors.ts +4 -0
- package/src/mcpl/inbound-source.ts +2 -2
- package/src/mcpl/inference-router.ts +67 -10
- package/src/mcpl/modern-connection.ts +83 -68
- package/src/mcpl/protocol-family.ts +37 -4
- package/src/mcpl/push-coalescer.ts +21 -7
- package/src/mcpl/references.ts +3 -4
- package/src/mcpl/server-connection.ts +30 -21
- package/src/mcpl/tool-signature.ts +18 -11
- package/src/mcpl/toolsets-module.ts +7 -0
- package/src/mcpl/transport.ts +261 -60
- package/src/mcpl/types.ts +18 -1
- package/src/module-registry.ts +178 -25
- package/src/modules/discord/discord-js-client.ts +33 -29
- package/src/modules/sender-name.ts +8 -5
- package/src/modules/workspace/disk-agreement.ts +39 -15
- package/src/modules/workspace/index.ts +65 -14
- package/src/modules/workspace/observe.ts +51 -10
- package/src/modules/workspace/reconcile.ts +22 -8
- package/src/modules/workspace/types.ts +5 -0
- package/src/modules/workspace/watcher.ts +8 -6
- package/src/notice-tags.ts +2 -0
- package/src/recovery/discord-awareness-outbox.ts +1 -11
- package/src/silent-heartbeat.ts +7 -4
- package/src/stored-injections.ts +7 -0
- package/src/supplied-text.ts +17 -6
- package/src/tool-result-guard.ts +1 -1
- package/src/tune-out/coordinator.ts +1374 -141
- package/src/tune-out/tools.ts +166 -13
- package/src/types/agent.ts +30 -1
- package/src/types/framework.ts +157 -15
- package/src/types/module.ts +42 -3
- package/src/types/trace.ts +154 -3
|
@@ -5,15 +5,16 @@
|
|
|
5
5
|
* auto-sync between real filesystem and Chronicle, and manual materialization.
|
|
6
6
|
*/
|
|
7
7
|
import { NOTICE_TAG } from '../../notice-tags.js';
|
|
8
|
+
import { nameToTypeBack } from '../../supplied-text.js';
|
|
8
9
|
import { constants as fsConstants } from 'node:fs';
|
|
9
10
|
import { open, readdir, readlink, stat, lstat, realpath } from 'node:fs/promises';
|
|
10
11
|
import { basename, dirname, isAbsolute, join, parse, resolve, relative, sep } from 'node:path';
|
|
11
12
|
import { WORKSPACE_FS_EVENT_TYPES, opToEventType } from './types.js';
|
|
12
13
|
import { MountWatcher } from './watcher.js';
|
|
13
14
|
import { hashContent, storedBytes, DEFAULT_MAX_FILE_SIZE } from './sync.js';
|
|
14
|
-
import { DiskAgreement, EvidenceUnavailable, callGate, sameRootIdentity } from './disk-agreement.js';
|
|
15
|
+
import { DiskAgreement, EvidenceUnavailable, callGate, rootUnreadable, sameRootIdentity } from './disk-agreement.js';
|
|
15
16
|
import { BranchIntents } from './branch-intent.js';
|
|
16
|
-
import { CHANGED, DIRECTORY, IGNORED, NONBLOCK, OTHER_MOUNT, OUTSIDE_INCLUDE, ROOT_REPLACED, ROOT_UNAVAILABLE, beneathRoot, checkDir, checkRoot, confirmAbsent, coversLanding, directoryAt, diskSpelling, filesystemTrustsCtime, foldsCase, inOtherMount, insideMount, leadsInto, linkOnTheWay, linkRefusal, linkWords, locateRoot, looksBinary, namesHolder, nestedAtReal, nestedGuess, nestedHolder, nestedStep, observePath, parsedSpelling, passedOverAt, pathSegments, patternRefusal, readBytes, readPrefix, restBeneath, rootAbsence, sameRoot, shownLeads, sniffImageMime, surelyAtRoot, walkScope, withinIncludes } from './observe.js';
|
|
17
|
+
import { CHANGED, DIRECTORY, IGNORED, NONBLOCK, OTHER_MOUNT, OUTSIDE_INCLUDE, ROOT_ON_ANOTHER_DEVICE, ROOT_REPLACED, ROOT_UNAVAILABLE, beneathRoot, checkDir, checkRoot, confirmAbsent, coversLanding, directoryAt, diskSpelling, filesystemTrustsCtime, foldsCase, inOtherMount, insideMount, leadsInto, linkOnTheWay, linkRefusal, linkWords, locateRoot, looksBinary, namesHolder, nestedAtReal, nestedGuess, nestedHolder, nestedStep, observePath, parsedSpelling, passedOverAt, pathSegments, patternRefusal, readBytes, readPrefix, restBeneath, rootAbsence, sameRoot, shownLeads, sniffImageMime, surelyAtRoot, walkScope, withinIncludes } from './observe.js';
|
|
17
18
|
import { TOOL_BATCH_HOOK_TIMEOUT_MS, ensureStateRegistered } from '../../module-registry.js';
|
|
18
19
|
import { DEFAULT_TOOL_RESULT_INLINE_MAX_CHARS } from '../../tool-result-history.js';
|
|
19
20
|
import { countBudget, decodeForEdit, hintBudget, planFile } from './edit-plan.js';
|
|
@@ -21,7 +22,7 @@ import { cutLine, editList, editReceipt, fitted, refusalText } from './edit-text
|
|
|
21
22
|
import { fileText } from './text.js';
|
|
22
23
|
import { DEFAULT_READ_LINE_LIMIT, characterPage, linePage } from './read-page.js';
|
|
23
24
|
import { grepText, textAnswer } from './result-text.js';
|
|
24
|
-
import { NOT_PUSHED_IN_OTHER_MOUNT, WALK_CAP, entryMode, explained, pushPaths, reconcilePass, settleAdoptionBeforeMutation, wayOn, } from './reconcile.js';
|
|
25
|
+
import { NOT_PUSHED_IN_OTHER_MOUNT, WALK_CAP, entryMode, explained, passRoot, pushPaths, reconcilePass, settleAdoptionBeforeMutation, wayOn, } from './reconcile.js';
|
|
25
26
|
import { EffectFailed, unlinkContained } from './effects.js';
|
|
26
27
|
import { AWAITS_REOPEN, MOUNT_IT, ROOT_RECHECK, Refusal, UNFOLLOWED_STEP, changesFiles, didNothing, errnoCode, errnoWayOn, errnoWords, hostFix, onlyTheHost, systemWords, unexpectedAnswer } from './answers.js';
|
|
27
28
|
import { unknownToolMessage } from '../unknown-tool.js';
|
|
@@ -61,6 +62,17 @@ const DIRECT_READS_AT_ONCE = 16;
|
|
|
61
62
|
const DIRECT_SYNC_SKIPPED = "a direct mount: its tools read disk as it is, so there's nothing to take in";
|
|
62
63
|
/** Why materialize passes over a writable direct mount, as its result's `skipped` says. */
|
|
63
64
|
const DIRECT_MATERIALIZE_SKIPPED = "a direct mount: its writes are on disk as they're made, so there's nothing to write";
|
|
65
|
+
const NOTHING_RECORDED_YET = 'nothing is recorded of this root yet, so any directory at its path is taken as it';
|
|
66
|
+
const NOTHING_RECORDED = `${NOTHING_RECORDED_YET}; the first sync that takes in a file, or materialize that writes one, records it`;
|
|
67
|
+
const NOTHING_RECORDED_READ_ONLY = `${NOTHING_RECORDED_YET}; the first sync that takes in a file records it`;
|
|
68
|
+
const BORN_UNRECORDED = 'no birth time is recorded of this root yet, so a directory made again in its place with the same inode can\'t be told from it; the next sync or ls of this mount records it';
|
|
69
|
+
function asShown(identity) {
|
|
70
|
+
if (identity?.born === undefined)
|
|
71
|
+
return identity;
|
|
72
|
+
const ns = BigInt(identity.born);
|
|
73
|
+
const second = new Date(Number(ns / 1000000000n) * 1000).toISOString().replace(/\.000Z$/, '');
|
|
74
|
+
return { ...identity, born: `${second}.${String(ns % 1000000000n).padStart(9, '0')}Z` };
|
|
75
|
+
}
|
|
64
76
|
class WorkspaceImageReadError extends Refusal {
|
|
65
77
|
reason;
|
|
66
78
|
constructor(reason, wayOn) {
|
|
@@ -1106,6 +1118,8 @@ export class WorkspaceModule {
|
|
|
1106
1118
|
/** One disk→store pass; the caller holds the mount's turn. Emits its events. */
|
|
1107
1119
|
async passUnlocked(mount, scope, opts = {}) {
|
|
1108
1120
|
const result = await reconcilePass(this.getStore(), this.agreementOrThrow(), await this.runtime(mount), scope, opts);
|
|
1121
|
+
if (result.rootListed !== undefined)
|
|
1122
|
+
mount.lastPassRoot = { at: new Date().toISOString(), listed: result.rootListed };
|
|
1109
1123
|
if (scope.kind === 'dir' && scope.dir === '' && scope.recursive)
|
|
1110
1124
|
mount.initialSyncDone = true;
|
|
1111
1125
|
// What a pass says is another mount's directory names that mount and
|
|
@@ -2005,14 +2019,14 @@ export class WorkspaceModule {
|
|
|
2005
2019
|
return { requestInference: true };
|
|
2006
2020
|
let text;
|
|
2007
2021
|
if (paths.length === 1) {
|
|
2008
|
-
text = `[${NOTICE_TAG.workspaceEvent} · ${op} · ${paths[0]}]`;
|
|
2022
|
+
text = `[${NOTICE_TAG.workspaceEvent} · ${op} · ${nameToTypeBack(paths[0])}]`;
|
|
2009
2023
|
}
|
|
2010
2024
|
else {
|
|
2011
|
-
const list = paths.map(p => `- ${p}`).join('\n');
|
|
2025
|
+
const list = paths.map(p => `- ${nameToTypeBack(p)}`).join('\n');
|
|
2012
2026
|
text = `[${NOTICE_TAG.workspaceEvent} · ${op} · ${paths.length} files in ${mountName}/]\n${list}`;
|
|
2013
2027
|
}
|
|
2014
2028
|
if (conflicts && conflicts.length > 0) {
|
|
2015
|
-
text += `\n[${NOTICE_TAG.conflictsWithDisk}: ${conflicts.join(', ')}; reading each shows how to settle it]`;
|
|
2029
|
+
text += `\n[${NOTICE_TAG.conflictsWithDisk}: ${conflicts.map(nameToTypeBack).join(', ')}; reading each shows how to settle it]`;
|
|
2016
2030
|
}
|
|
2017
2031
|
return {
|
|
2018
2032
|
requestInference: true,
|
|
@@ -2078,7 +2092,7 @@ export class WorkspaceModule {
|
|
|
2078
2092
|
/**
|
|
2079
2093
|
* Write binary content (e.g. an image pulled from the agent's context) to a
|
|
2080
2094
|
* mount, through the same Chronicle-tree + auto-materialize path as the
|
|
2081
|
-
* `write` tool. Public API for the framework's synthesized `
|
|
2095
|
+
* `write` tool. Public API for the framework's synthesized `save_recent_image`
|
|
2082
2096
|
* tool and other peer callers that hold bytes rather than text.
|
|
2083
2097
|
*
|
|
2084
2098
|
* `branch`, when given, ties the write to that branch: the store's current
|
|
@@ -2910,8 +2924,9 @@ export class WorkspaceModule {
|
|
|
2910
2924
|
* observation checks it (checkRoot), so the read and the evidence agree on
|
|
2911
2925
|
* which directory the mount is. Once the workspace has recorded the root's
|
|
2912
2926
|
* identity, a root that resolves to any other directory is refused, in
|
|
2913
|
-
* ROOT_REPLACED's words
|
|
2914
|
-
*
|
|
2927
|
+
* ROOT_REPLACED's words, or ROOT_ON_ANOTHER_DEVICE's where only its device
|
|
2928
|
+
* differs and birth times can't tell; with none recorded yet, it need only
|
|
2929
|
+
* be a directory there. A refusal where no directory is at the root's path
|
|
2915
2930
|
* carries the errno that gives (rootAbsence: ENOENT when nothing is there
|
|
2916
2931
|
* and ENOTDIR when something else is, which a caller can read as no file,
|
|
2917
2932
|
* or the errno the root's stat failed with otherwise, such as EACCES). A
|
|
@@ -3751,9 +3766,7 @@ export class WorkspaceModule {
|
|
|
3751
3766
|
const absent = err instanceof WorkspaceReadError && err.code !== 'mount_unavailable' && (err.errno === 'ENOENT' || err.errno === 'ENOTDIR');
|
|
3752
3767
|
if (!absent)
|
|
3753
3768
|
return { unreadable: containedRefusal(err, path) };
|
|
3754
|
-
const
|
|
3755
|
-
const rootReal = await realpath(root).catch(() => root);
|
|
3756
|
-
const view = this.viewOf(mount, this.agreementOrThrow().rootIdentityForRead(mount.config.name));
|
|
3769
|
+
const { view, rootReal } = await this.readView(mount);
|
|
3757
3770
|
const proof = await confirmAbsent(view, rootReal, relativePath);
|
|
3758
3771
|
if (!('reason' in proof))
|
|
3759
3772
|
return 'none';
|
|
@@ -5502,6 +5515,8 @@ export class WorkspaceModule {
|
|
|
5502
5515
|
if (input.mount !== undefined && !this.mounts.has(input.mount)) {
|
|
5503
5516
|
return { success: false, error: didNothing('status', this.noSuchMountField(input.mount, 'covers every mount')), isError: true };
|
|
5504
5517
|
}
|
|
5518
|
+
const asked = input.mount === undefined ? [] : [...this.mounts].filter(([name, mount]) => !mount.direct && name === input.mount);
|
|
5519
|
+
const roots = new Map(await Promise.all(asked.map(async ([name, mount]) => [name, await this.rootState(mount)])));
|
|
5505
5520
|
for (const [name, mount] of this.mounts) {
|
|
5506
5521
|
if (input.mount !== undefined && name !== input.mount)
|
|
5507
5522
|
continue;
|
|
@@ -5520,6 +5535,8 @@ export class WorkspaceModule {
|
|
|
5520
5535
|
const { conflicts: conflictPaths, deletions: deletionPaths, owed } = this.heldChanges(mount);
|
|
5521
5536
|
const pending = new Set([...conflictPaths, ...deletionPaths, ...owed]);
|
|
5522
5537
|
const currentBranch = store.currentBranch();
|
|
5538
|
+
const root = input.mount !== undefined ? roots.get(name)
|
|
5539
|
+
: mount.lastPassRoot?.listed ? { unavailable: mount.lastPassRoot.listed, lastPassAt: mount.lastPassRoot.at } : undefined;
|
|
5523
5540
|
status[name] = {
|
|
5524
5541
|
path: mount.config.path,
|
|
5525
5542
|
mode: mount.config.backend === 'direct' ? mount.config.mode ?? 'read-write' : mount.config.mode,
|
|
@@ -5537,12 +5554,41 @@ export class WorkspaceModule {
|
|
|
5537
5554
|
initialSyncDone: mount.initialSyncDone,
|
|
5538
5555
|
currentBranch: currentBranch.name,
|
|
5539
5556
|
lastMaterializedBranch: mount.lastMaterializedBranchId,
|
|
5540
|
-
canMaterialize: this.mountMaterializeBlockReason(store, mount) === null,
|
|
5557
|
+
canMaterialize: this.mountMaterializeBlockReason(store, mount) === null && root?.unavailable === undefined,
|
|
5541
5558
|
...(mount.lastAgentActionScan ? { lastAgentActionScan: mount.lastAgentActionScan } : {}),
|
|
5559
|
+
...(root !== undefined ? { root } : {}),
|
|
5542
5560
|
};
|
|
5543
5561
|
}
|
|
5544
5562
|
return { success: true, data: status };
|
|
5545
5563
|
}
|
|
5564
|
+
async readView(mount) {
|
|
5565
|
+
const root = resolve(mount.config.path);
|
|
5566
|
+
const rootReal = await realpath(root).catch(() => root);
|
|
5567
|
+
return { view: this.viewOf(mount, this.agreementOrThrow().rootIdentityForRead(mount.config.name)), rootReal };
|
|
5568
|
+
}
|
|
5569
|
+
async rootState(mount) {
|
|
5570
|
+
const read = await this.readView(mount).catch((err) => {
|
|
5571
|
+
if (err instanceof EvidenceUnavailable)
|
|
5572
|
+
return err;
|
|
5573
|
+
throw err;
|
|
5574
|
+
});
|
|
5575
|
+
if (read instanceof EvidenceUnavailable) {
|
|
5576
|
+
const root = resolve(mount.config.path);
|
|
5577
|
+
const there = await locateRoot(this.viewOf(mount, undefined), await realpath(root).catch(() => root));
|
|
5578
|
+
return { now: asShown('identity' in there ? there.identity : null), unavailable: rootUnreadable(read) };
|
|
5579
|
+
}
|
|
5580
|
+
const { view, rootReal } = read;
|
|
5581
|
+
const recorded = view.rootIdentity ?? null;
|
|
5582
|
+
const found = await passRoot({ view, rootReal });
|
|
5583
|
+
if ('unavailable' in found) {
|
|
5584
|
+
const there = await locateRoot({ ...view, rootIdentity: undefined }, rootReal);
|
|
5585
|
+
return { recorded: asShown(recorded), now: asShown('identity' in there ? there.identity : null), unavailable: found.listed };
|
|
5586
|
+
}
|
|
5587
|
+
const note = this.agreementOrThrow().awaitsReopen ? undefined
|
|
5588
|
+
: recorded === null ? mount.config.mode === 'read-only' ? NOTHING_RECORDED_READ_ONLY : NOTHING_RECORDED
|
|
5589
|
+
: recorded.born === undefined && found.identity.born !== undefined && found.bornFixed ? BORN_UNRECORDED : undefined;
|
|
5590
|
+
return { recorded: asShown(recorded), now: asShown(found.identity), ...(note !== undefined ? { note } : {}) };
|
|
5591
|
+
}
|
|
5546
5592
|
/**
|
|
5547
5593
|
* What the store holds of a mount that disk lacks, on the selected branch,
|
|
5548
5594
|
* among the mount's own paths. Status counts the first three as pending:
|
|
@@ -6069,7 +6115,7 @@ export class WorkspaceModule {
|
|
|
6069
6115
|
return false; // still missing: the pass says so
|
|
6070
6116
|
const agreement = this.agreementOrThrow();
|
|
6071
6117
|
const recorded = agreement.rootIdentity(mount.config.name);
|
|
6072
|
-
if (recorded && sameRootIdentity(recorded, found.identity))
|
|
6118
|
+
if (recorded && sameRootIdentity(recorded, found.identity, found.bornFixed))
|
|
6073
6119
|
return false;
|
|
6074
6120
|
if (recorded)
|
|
6075
6121
|
agreement.acceptRoot(mount.config.name, found.identity);
|
|
@@ -6477,7 +6523,7 @@ function deletedOnDisk(path) {
|
|
|
6477
6523
|
function uncheckedFile(shown, note, cause) {
|
|
6478
6524
|
if (note === DIRECTORY)
|
|
6479
6525
|
return `${shown} is a directory, not a file; ls ${shown} lists what's in it.`;
|
|
6480
|
-
const on = note === ROOT_REPLACED || cause.ownStep === true ? null
|
|
6526
|
+
const on = note === ROOT_REPLACED || note === ROOT_ON_ANOTHER_DEVICE || cause.ownStep === true ? null
|
|
6481
6527
|
: (note === undefined ? null : wayOn(note, cause, 'read')) ?? 'calling again checks disk again; if the same reason comes back, whoever runs this host can fix it on disk';
|
|
6482
6528
|
return `${shown} isn't in the workspace, and disk couldn't be checked: ${sentence(note ?? 'not observed')}${on !== null ? ` ${on[0].toUpperCase()}${sentence(on.slice(1))}` : ''}`;
|
|
6483
6529
|
}
|