@animalabs/agent-framework 0.26.2 → 0.28.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 +99 -8
- package/dist/src/agent.d.ts +291 -23
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +596 -61
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +5 -4
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/auto-continue.d.ts +34 -0
- package/dist/src/auto-continue.d.ts.map +1 -0
- package/dist/src/auto-continue.js +36 -0
- package/dist/src/auto-continue.js.map +1 -0
- package/dist/src/code-execution/isolate/scripts.d.ts +11 -0
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +5 -1
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/cut-off-round.d.ts +24 -0
- package/dist/src/cut-off-round.d.ts.map +1 -0
- package/dist/src/cut-off-round.js +87 -0
- package/dist/src/cut-off-round.js.map +1 -0
- package/dist/src/framework.d.ts +1038 -193
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +5967 -1514
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +405 -46
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +2646 -399
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/index.d.ts +3 -2
- package/dist/src/gate/index.d.ts.map +1 -1
- package/dist/src/gate/index.js +2 -1
- package/dist/src/gate/index.js.map +1 -1
- package/dist/src/gate/recipe-reconcile.d.ts +103 -0
- package/dist/src/gate/recipe-reconcile.d.ts.map +1 -0
- package/dist/src/gate/recipe-reconcile.js +325 -0
- package/dist/src/gate/recipe-reconcile.js.map +1 -0
- package/dist/src/gate/reply-judge.d.ts +116 -0
- package/dist/src/gate/reply-judge.d.ts.map +1 -0
- package/dist/src/gate/reply-judge.js +467 -0
- package/dist/src/gate/reply-judge.js.map +1 -0
- package/dist/src/gate/types.d.ts +229 -8
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/heartbeat/heartbeat.d.ts +184 -0
- package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
- package/dist/src/heartbeat/heartbeat.js +752 -0
- package/dist/src/heartbeat/heartbeat.js.map +1 -0
- package/dist/src/heartbeat/reminder-time.d.ts +5 -0
- package/dist/src/heartbeat/reminder-time.d.ts.map +1 -0
- package/dist/src/heartbeat/reminder-time.js +107 -0
- package/dist/src/heartbeat/reminder-time.js.map +1 -0
- package/dist/src/index.d.ts +10 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-mask.d.ts.map +1 -1
- package/dist/src/mcpl/capability-mask.js +3 -2
- package/dist/src/mcpl/capability-mask.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +433 -113
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +1154 -435
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts +16 -8
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/conversation-router.js +29 -15
- package/dist/src/mcpl/conversation-router.js.map +1 -1
- package/dist/src/mcpl/convert-block.d.ts.map +1 -1
- package/dist/src/mcpl/convert-block.js +14 -2
- package/dist/src/mcpl/convert-block.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts +7 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.js +32 -7
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +26 -10
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +40 -69
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +5 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +4 -0
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +14 -2
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +73 -28
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/prose-grammar.d.ts +4 -0
- package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
- package/dist/src/mcpl/prose-grammar.js +6 -0
- package/dist/src/mcpl/prose-grammar.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +3 -0
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +20 -2
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +33 -11
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts +63 -42
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +177 -145
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +380 -46
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +736 -77
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +93 -4
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +176 -11
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tags.d.ts +9 -2
- package/dist/src/mcpl/tags.d.ts.map +1 -1
- package/dist/src/mcpl/tags.js +12 -2
- package/dist/src/mcpl/tags.js.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.d.ts +11 -0
- package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.js +21 -0
- package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
- package/dist/src/mcpl/tool-presence.d.ts +311 -0
- package/dist/src/mcpl/tool-presence.d.ts.map +1 -0
- package/dist/src/mcpl/tool-presence.js +697 -0
- package/dist/src/mcpl/tool-presence.js.map +1 -0
- package/dist/src/mcpl/tool-result-normalize.d.ts +9 -3
- package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
- package/dist/src/mcpl/tool-result-normalize.js +14 -6
- package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
- package/dist/src/mcpl/tool-signature.d.ts +46 -0
- package/dist/src/mcpl/tool-signature.d.ts.map +1 -0
- package/dist/src/mcpl/tool-signature.js +321 -0
- package/dist/src/mcpl/tool-signature.js.map +1 -0
- package/dist/src/mcpl/toolset-host.d.ts +251 -0
- package/dist/src/mcpl/toolset-host.d.ts.map +1 -0
- package/dist/src/mcpl/toolset-host.js +720 -0
- package/dist/src/mcpl/toolset-host.js.map +1 -0
- package/dist/src/mcpl/toolsets-module.d.ts +83 -0
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -0
- package/dist/src/mcpl/toolsets-module.js +523 -0
- package/dist/src/mcpl/toolsets-module.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts +2 -2
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +3 -2
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +24 -2
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/mcpl/visible-content.d.ts +7 -9
- package/dist/src/mcpl/visible-content.d.ts.map +1 -1
- package/dist/src/mcpl/visible-content.js +21 -9
- package/dist/src/mcpl/visible-content.js.map +1 -1
- package/dist/src/module-registry.d.ts +27 -9
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +77 -17
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.js +1 -1
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +2 -1
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +73 -28
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +108 -6
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +273 -57
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/answers.d.ts +22 -0
- package/dist/src/modules/workspace/answers.d.ts.map +1 -0
- package/dist/src/modules/workspace/answers.js +123 -0
- package/dist/src/modules/workspace/answers.js.map +1 -0
- package/dist/src/modules/workspace/branch-intent.d.ts +5 -3
- package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
- package/dist/src/modules/workspace/branch-intent.js +6 -2
- package/dist/src/modules/workspace/branch-intent.js.map +1 -1
- package/dist/src/modules/workspace/direct-write.d.ts +184 -0
- package/dist/src/modules/workspace/direct-write.d.ts.map +1 -0
- package/dist/src/modules/workspace/direct-write.js +417 -0
- package/dist/src/modules/workspace/direct-write.js.map +1 -0
- package/dist/src/modules/workspace/disk-agreement.d.ts +33 -11
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +48 -17
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/edit-text.d.ts +27 -12
- package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
- package/dist/src/modules/workspace/edit-text.js +61 -29
- package/dist/src/modules/workspace/edit-text.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +10 -0
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +21 -14
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +308 -78
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +2103 -720
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +75 -63
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +366 -180
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/read-page.d.ts +41 -0
- package/dist/src/modules/workspace/read-page.d.ts.map +1 -0
- package/dist/src/modules/workspace/read-page.js +219 -0
- package/dist/src/modules/workspace/read-page.js.map +1 -0
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +26 -16
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/result-text.d.ts +68 -0
- package/dist/src/modules/workspace/result-text.d.ts.map +1 -0
- package/dist/src/modules/workspace/result-text.js +94 -0
- package/dist/src/modules/workspace/result-text.js.map +1 -0
- package/dist/src/modules/workspace/sync.d.ts +9 -0
- package/dist/src/modules/workspace/sync.d.ts.map +1 -1
- package/dist/src/modules/workspace/sync.js +14 -0
- package/dist/src/modules/workspace/sync.js.map +1 -1
- package/dist/src/modules/workspace/text.d.ts +29 -12
- package/dist/src/modules/workspace/text.d.ts.map +1 -1
- package/dist/src/modules/workspace/text.js +35 -33
- package/dist/src/modules/workspace/text.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +137 -60
- 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.map +1 -1
- package/dist/src/modules/workspace/watcher.js +8 -3
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/prose-drafts.d.ts +4 -3
- package/dist/src/prose-drafts.d.ts.map +1 -1
- package/dist/src/prose-drafts.js +3 -2
- package/dist/src/prose-drafts.js.map +1 -1
- package/dist/src/reasoning-loss-notice.d.ts +23 -0
- package/dist/src/reasoning-loss-notice.d.ts.map +1 -0
- package/dist/src/reasoning-loss-notice.js +50 -0
- package/dist/src/reasoning-loss-notice.js.map +1 -0
- package/dist/src/reasoning-loss.d.ts +24 -0
- package/dist/src/reasoning-loss.d.ts.map +1 -0
- package/dist/src/reasoning-loss.js +102 -0
- package/dist/src/reasoning-loss.js.map +1 -0
- package/dist/src/send-tools.d.ts +3 -2
- package/dist/src/send-tools.d.ts.map +1 -1
- package/dist/src/send-tools.js +3 -2
- package/dist/src/send-tools.js.map +1 -1
- package/dist/src/sent-rows.d.ts +59 -0
- package/dist/src/sent-rows.d.ts.map +1 -0
- package/dist/src/sent-rows.js +145 -0
- package/dist/src/sent-rows.js.map +1 -0
- package/dist/src/silent-heartbeat.d.ts +17 -10
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/stable-hash.d.ts +3 -0
- package/dist/src/stable-hash.d.ts.map +1 -0
- package/dist/src/stable-hash.js +15 -0
- package/dist/src/stable-hash.js.map +1 -0
- package/dist/src/stored-injections.d.ts +99 -0
- package/dist/src/stored-injections.d.ts.map +1 -0
- package/dist/src/stored-injections.js +106 -0
- package/dist/src/stored-injections.js.map +1 -0
- package/dist/src/text-as-stored.d.ts +4 -3
- package/dist/src/text-as-stored.d.ts.map +1 -1
- package/dist/src/text-as-stored.js +4 -3
- package/dist/src/text-as-stored.js.map +1 -1
- package/dist/src/thinking-drops.d.ts +74 -0
- package/dist/src/thinking-drops.d.ts.map +1 -0
- package/dist/src/thinking-drops.js +96 -0
- package/dist/src/thinking-drops.js.map +1 -0
- package/dist/src/tool-args.d.ts +12 -0
- package/dist/src/tool-args.d.ts.map +1 -1
- package/dist/src/tool-args.js +35 -1
- package/dist/src/tool-args.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts +9 -8
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js +9 -8
- package/dist/src/tool-image-ledger.js.map +1 -1
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +3 -1
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +12 -6
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +44 -17
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tool-result-history.d.ts +176 -24
- package/dist/src/tool-result-history.d.ts.map +1 -1
- package/dist/src/tool-result-history.js +411 -91
- package/dist/src/tool-result-history.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +17 -9
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +84 -37
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +4 -1
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/types/agent.d.ts +217 -7
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +33 -9
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +39 -3
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +95 -9
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +91 -3
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/agent.ts +661 -67
- package/src/api/server.ts +5 -4
- package/src/auto-continue.ts +43 -0
- package/src/code-execution/isolate/scripts.ts +11 -3
- package/src/cut-off-round.ts +98 -0
- package/src/framework.ts +6168 -1540
- package/src/gate/event-gate.ts +2895 -405
- package/src/gate/index.ts +10 -1
- package/src/gate/recipe-reconcile.ts +355 -0
- package/src/gate/reply-judge.ts +512 -0
- package/src/gate/types.ts +234 -9
- package/src/heartbeat/heartbeat.ts +804 -0
- package/src/heartbeat/reminder-time.ts +107 -0
- package/src/index.ts +11 -4
- package/src/mcpl/capability-mask.ts +3 -2
- package/src/mcpl/channel-registry.ts +1222 -468
- package/src/mcpl/conversation-router.ts +34 -16
- package/src/mcpl/convert-block.ts +14 -1
- package/src/mcpl/hook-orchestrator.ts +33 -6
- package/src/mcpl/inbound-source.ts +42 -69
- package/src/mcpl/index.ts +6 -1
- package/src/mcpl/inference-router.ts +79 -34
- package/src/mcpl/prose-grammar.ts +7 -0
- package/src/mcpl/protocol-family.ts +2 -0
- package/src/mcpl/push-coalescer.ts +51 -13
- package/src/mcpl/reference-fetcher.ts +201 -162
- package/src/mcpl/references.ts +851 -77
- package/src/mcpl/server-connection.ts +189 -11
- package/src/mcpl/tags.ts +13 -2
- package/src/mcpl/tool-lifecycle.ts +21 -0
- package/src/mcpl/tool-presence.ts +716 -0
- package/src/mcpl/tool-result-normalize.ts +18 -6
- package/src/mcpl/tool-signature.ts +316 -0
- package/src/mcpl/toolset-host.ts +727 -0
- package/src/mcpl/toolsets-module.ts +545 -0
- package/src/mcpl/transport.ts +3 -2
- package/src/mcpl/types.ts +25 -2
- package/src/mcpl/visible-content.ts +22 -9
- package/src/module-registry.ts +85 -26
- package/src/modules/discord/index.ts +1 -1
- package/src/modules/history/index.ts +70 -30
- package/src/modules/history/semantic.ts +308 -54
- package/src/modules/workspace/answers.ts +133 -0
- package/src/modules/workspace/branch-intent.ts +10 -5
- package/src/modules/workspace/direct-write.ts +460 -0
- package/src/modules/workspace/disk-agreement.ts +52 -21
- package/src/modules/workspace/edit-text.ts +84 -35
- package/src/modules/workspace/effects.ts +22 -13
- package/src/modules/workspace/index.ts +2142 -723
- package/src/modules/workspace/observe.ts +381 -177
- package/src/modules/workspace/read-page.ts +228 -0
- package/src/modules/workspace/reconcile.ts +27 -15
- package/src/modules/workspace/result-text.ts +121 -0
- package/src/modules/workspace/sync.ts +16 -0
- package/src/modules/workspace/text.ts +58 -32
- package/src/modules/workspace/types.ts +137 -60
- package/src/modules/workspace/watcher.ts +8 -3
- package/src/prose-drafts.ts +4 -3
- package/src/reasoning-loss-notice.ts +62 -0
- package/src/reasoning-loss.ts +120 -0
- package/src/send-tools.ts +3 -2
- package/src/sent-rows.ts +162 -0
- package/src/silent-heartbeat.ts +17 -10
- package/src/stable-hash.ts +14 -0
- package/src/stored-injections.ts +131 -0
- package/src/text-as-stored.ts +4 -3
- package/src/thinking-drops.ts +135 -0
- package/src/tool-args.ts +34 -1
- package/src/tool-image-ledger.ts +9 -8
- package/src/tool-presentation.ts +3 -1
- package/src/tool-result-guard.ts +45 -17
- package/src/tool-result-history.ts +471 -90
- package/src/tune-out/coordinator.ts +80 -37
- package/src/tune-out/tools.ts +4 -1
- package/src/types/agent.ts +220 -7
- package/src/types/events.ts +33 -9
- package/src/types/framework.ts +36 -3
- package/src/types/module.ts +91 -9
- package/src/types/trace.ts +94 -3
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
* and EditMany tools' answers.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import type { ToolResult } from '../../types/events.js';
|
|
14
15
|
import { type Change, type FilePlan, type Leaves, type MatchProblem, SHOWN_MATCHES } from './edit-plan.js';
|
|
15
|
-
import {
|
|
16
|
+
import { answerText, fieldLine, sectionLead, sectionText, shownValue, textAnswer, type DiskState } from './result-text.js';
|
|
17
|
+
import { MAX_LINE_CHARS, numberedLine, safeCut } from './text.js';
|
|
16
18
|
|
|
17
19
|
/** The tool a call came through, which words its refusals and receipt. */
|
|
18
20
|
export type EditTool = 'edit' | 'edit_many';
|
|
@@ -190,8 +192,13 @@ function label(problem: EditProblem): string {
|
|
|
190
192
|
*/
|
|
191
193
|
const FIRST_LINE_MAX = 400;
|
|
192
194
|
|
|
193
|
-
/**
|
|
194
|
-
|
|
195
|
+
/**
|
|
196
|
+
* What an answer is: a refusal, whose problems the agent answers and sends
|
|
197
|
+
* again; the answer to edits stored, which mustn't be sent again; or, on a
|
|
198
|
+
* direct mount, the answer to an edit_many call written partway, whose parts
|
|
199
|
+
* are each file's outcome.
|
|
200
|
+
*/
|
|
201
|
+
export type AnswerKind = 'refusal' | 'stored' | 'written';
|
|
195
202
|
|
|
196
203
|
/** A line cut to FIRST_LINE_MAX, as a part's first line is, and as a thrown message is in an answer's head. */
|
|
197
204
|
export function cutLine(line: string): string {
|
|
@@ -205,18 +212,25 @@ export function cutLine(line: string): string {
|
|
|
205
212
|
* shown and send the call again to see the rest: once those are answered,
|
|
206
213
|
* their room can show the rest, details included. For edits stored, the
|
|
207
214
|
* problems are the files disk refused, and a last line that leaves some out
|
|
208
|
-
* points to ls.
|
|
215
|
+
* points to ls. For edits written partway, they're each file's outcome, and
|
|
216
|
+
* one that leaves some out points to read.
|
|
209
217
|
*/
|
|
210
218
|
function tailText(kind: AnswerKind, maxChars: number, cut: number, problems: number, notes: number, anyShown: boolean): string {
|
|
211
219
|
const items = [
|
|
212
220
|
...(cut ? [`the details of ${cut} of these`] : []),
|
|
213
|
-
...(problems
|
|
221
|
+
...(problems
|
|
222
|
+
? [kind === 'refusal'
|
|
223
|
+
? `${problems} more ${plural(problems, 'problem')}`
|
|
224
|
+
: kind === 'stored' ? `${problems} more ${plural(problems, 'file')} disk refused` : `the outcomes of ${problems} more ${plural(problems, 'file')}`]
|
|
225
|
+
: []),
|
|
214
226
|
...(notes ? [`${notes} ${plural(notes, 'note')} on the files' copies on disk`] : []),
|
|
215
227
|
];
|
|
216
228
|
if (!items.length) return '';
|
|
217
229
|
const next = kind === 'stored'
|
|
218
230
|
? problems ? " ls shows each path's state." : ''
|
|
219
|
-
:
|
|
231
|
+
: kind === 'written'
|
|
232
|
+
? problems ? ' Reading a file shows it as disk has it now.' : ''
|
|
233
|
+
: problems && anyShown ? ' Answer the problems shown and send the call again to see the rest.' : '';
|
|
220
234
|
const list = items.length < 2 ? items[0] : `${items.slice(0, -1).join(', ')} and ${items.at(-1)}`;
|
|
221
235
|
return `[To keep this answer within ${maxChars.toLocaleString('en-US')} characters, it leaves out ${list}.${next}]`;
|
|
222
236
|
}
|
|
@@ -271,9 +285,10 @@ export function fitted(head: string, problems: string[], notes: string[], maxCha
|
|
|
271
285
|
* counts its problems and names each, in edit order, labelled with its edits.
|
|
272
286
|
* `notes` follow the problems: which copy of a file the edits looked in, and
|
|
273
287
|
* a conflict with disk, which the agent needs whether or not the call stored
|
|
274
|
-
* anything.
|
|
288
|
+
* anything. On a direct mount, whose edits go to disk with no store between
|
|
289
|
+
* (`verb` 'wrote'), edit_many says it wrote none.
|
|
275
290
|
*/
|
|
276
|
-
export function refusalText(tool: EditTool, problems: EditProblem[], notes: string[], maxChars: number): string {
|
|
291
|
+
export function refusalText(tool: EditTool, problems: EditProblem[], notes: string[], maxChars: number, verb: 'stored' | 'wrote' = 'stored'): string {
|
|
277
292
|
const sorted = [...problems].sort((a, b) => firstEdit(a) - firstEdit(b));
|
|
278
293
|
if (tool === 'edit') {
|
|
279
294
|
const [problem] = sorted;
|
|
@@ -281,7 +296,7 @@ export function refusalText(tool: EditTool, problems: EditProblem[], notes: stri
|
|
|
281
296
|
const whole = problem!.kind === 'file' && problem!.whole ? text : `The edit did nothing: ${text}`;
|
|
282
297
|
return fitted('', [whole], notes, maxChars, 'refusal');
|
|
283
298
|
}
|
|
284
|
-
const head = `The edit_many call
|
|
299
|
+
const head = `The edit_many call ${verb} none of its edits: ${sorted.length} ${plural(sorted.length, 'problem')}.`;
|
|
285
300
|
return fitted(head, sorted.map((problem) => `${label(problem)}${problemText(problem, tool)}`), notes, maxChars, 'refusal');
|
|
286
301
|
}
|
|
287
302
|
|
|
@@ -350,7 +365,7 @@ function excerptLine(line: string, n: number, columns: number[]): string {
|
|
|
350
365
|
|
|
351
366
|
/**
|
|
352
367
|
* Each edit's first change in a file, as numbered regions merged where they
|
|
353
|
-
* meet, while the budget lasts, counted as the answer's
|
|
368
|
+
* meet, while the budget lasts, counted as the answer's text holds them; past
|
|
354
369
|
* it, the regions are named by their lines.
|
|
355
370
|
*/
|
|
356
371
|
export function shownRegions(plan: FilePlan, budget: { left: number }, maxChars: number): string[] {
|
|
@@ -396,7 +411,7 @@ export function shownRegions(plan: FilePlan, budget: { left: number }, maxChars:
|
|
|
396
411
|
// region of millions of lines, which is named by its lines, isn't built
|
|
397
412
|
// whole first. The line before it ("…" between regions, or the line end)
|
|
398
413
|
// counts too, and each line feed between its lines.
|
|
399
|
-
let cost = out.length ?
|
|
414
|
+
let cost = out.length ? '\n…\n'.length : '\n'.length;
|
|
400
415
|
const lines: string[] = [];
|
|
401
416
|
let fits = !omitted.length;
|
|
402
417
|
for (let lineStart = region.start, n = region.from; fits && lineStart < region.end; n++) {
|
|
@@ -407,7 +422,7 @@ export function shownRegions(plan: FilePlan, budget: { left: number }, maxChars:
|
|
|
407
422
|
// changes start on it, a stretch from shortly before each.
|
|
408
423
|
const columns = text.length > MAX_LINE_CHARS ? firsts.filter((first) => first.line === n).map((first) => first.at - lineStart) : [];
|
|
409
424
|
const numberedText = columns.length ? excerptLine(text, n, columns) : numberedLine(text, n);
|
|
410
|
-
cost +=
|
|
425
|
+
cost += numberedText.length + (lines.length ? 1 : 0);
|
|
411
426
|
if (cost > budget.left) fits = false;
|
|
412
427
|
else lines.push(numberedText);
|
|
413
428
|
lineStart = lineEnd + 1;
|
|
@@ -507,24 +522,56 @@ function receiptReserve(tool: EditTool, files: StoredFile[], maxChars: number):
|
|
|
507
522
|
const listed = Math.min(SHOWN_MATCHES, plan.edits.length);
|
|
508
523
|
const range = `${last}–${last}`;
|
|
509
524
|
const note = regionsLeftOut(maxChars, Array.from({ length: listed }, () => range), plan.edits.length - listed, false);
|
|
510
|
-
regions = Math.max(regions,
|
|
525
|
+
regions = Math.max(regions, 1 + note.length);
|
|
511
526
|
}
|
|
512
527
|
if (tool === 'edit') return regions;
|
|
513
528
|
const most = files.length;
|
|
514
|
-
return regions +
|
|
529
|
+
return regions + 2 + filesLeftOut(maxChars, most, { notListed: most, unshown: most, notes: most, edits: most })!.length;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/** A file edit_many lists, as its receipt's fields hold it. */
|
|
533
|
+
interface ListedFile {
|
|
534
|
+
path: string;
|
|
535
|
+
size: number;
|
|
536
|
+
replacements: number;
|
|
537
|
+
modeKept?: string;
|
|
538
|
+
edits?: number[];
|
|
539
|
+
note?: string;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** edit_many's line for a file it lists: its path, size and replacements, and then the edits, the mode kept and the notes it has room for. */
|
|
543
|
+
function listedFileLine(file: ListedFile): string {
|
|
544
|
+
return `${shownValue(file.path)}: size ${file.size}, replacements ${file.replacements}`
|
|
545
|
+
+ (file.edits !== undefined ? `, edits ${file.edits.join(', ')}` : '')
|
|
546
|
+
+ (file.modeKept !== undefined ? `; modeKept: ${shownValue(file.modeKept)}` : '')
|
|
547
|
+
+ (file.note !== undefined ? `. ${shownValue(file.note)}` : '');
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** edit_many's receipt's text before its changed regions: its counts, and the files it lists. */
|
|
551
|
+
function manyHeadText(data: { edits: number; replacements: number; disk: DiskState; files: ListedFile[]; filesNotListed?: number }): string {
|
|
552
|
+
const header = [fieldLine('edits', data.edits), fieldLine('replacements', data.replacements), fieldLine('disk', data.disk)];
|
|
553
|
+
if (data.filesNotListed !== undefined) header.push(fieldLine('filesNotListed', data.filesNotListed));
|
|
554
|
+
return answerText(header, [sectionText('files', data.files.map(listedFileLine).join('\n'))]);
|
|
515
555
|
}
|
|
516
556
|
|
|
517
557
|
/**
|
|
518
558
|
* The receipt of edits stored: each file's size, replacements and notes, and
|
|
519
559
|
* each edit's first changed region, numbered as read numbers lines, held to
|
|
520
|
-
* `maxChars` as the answer's
|
|
521
|
-
* the regions take what is left, and past it a file's
|
|
522
|
-
* their lines. edit_many lists its files while they
|
|
523
|
-
* don't fit without them, or without its edits'
|
|
524
|
-
* rest. edit's receipt, of one file, keeps its
|
|
525
|
-
* region where those
|
|
560
|
+
* `maxChars` as the answer's text holds it (result-text.ts). Its counts and
|
|
561
|
+
* notes come first; the regions take what is left, and past it a file's
|
|
562
|
+
* regions are named by their lines. edit_many lists its files while they
|
|
563
|
+
* fit, a file whose notes don't fit without them, or without its edits'
|
|
564
|
+
* numbers too, and counts the rest. edit's receipt, of one file, keeps its
|
|
565
|
+
* counts and notes and shows no region where those leave no room for it. The
|
|
566
|
+
* line that names what a receipt leaves out comes after what it keeps, and
|
|
567
|
+
* where its counts and notes leave too little room for that line too, as
|
|
568
|
+
* they can with long notes or a limit far under the 1,000 a residence or an
|
|
569
|
+
* agent can set, the receipt passes `maxChars` by it, and then reaches its
|
|
570
|
+
* caller as any result past its limit does: a model's spills, and a script's
|
|
571
|
+
* call answers ResultTooLarge. Otherwise the model reads the text, and a
|
|
572
|
+
* script gets the receipt's fields beside it.
|
|
526
573
|
*/
|
|
527
|
-
export function editReceipt(tool: EditTool, files: StoredFile[], editCount: number, maxChars: number):
|
|
574
|
+
export function editReceipt(tool: EditTool, files: StoredFile[], editCount: number, maxChars: number, disk: DiskState): ToolResult {
|
|
528
575
|
const reserve = receiptReserve(tool, files, maxChars);
|
|
529
576
|
const notesOf = ({ plan, notes }: StoredFile): string[] => {
|
|
530
577
|
const lineEnds = lineEndNote(plan);
|
|
@@ -544,28 +591,30 @@ export function editReceipt(tool: EditTool, files: StoredFile[], editCount: numb
|
|
|
544
591
|
if (tool === 'edit') {
|
|
545
592
|
const file = files[0]!;
|
|
546
593
|
const notes = notesOf(file);
|
|
547
|
-
const
|
|
594
|
+
const head = {
|
|
548
595
|
path: file.path,
|
|
549
596
|
size: file.plan.bytes.length,
|
|
550
597
|
replacements: file.plan.replacements,
|
|
598
|
+
disk,
|
|
551
599
|
...(notes.length ? { note: notes.join(' ') } : {}),
|
|
552
600
|
...(file.modeKept ? { modeKept: file.modeKept } : {}),
|
|
553
|
-
changed: '',
|
|
554
601
|
};
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
602
|
+
const header = Object.entries(head).map(([key, value]) => fieldLine(key, value));
|
|
603
|
+
const budget = { left: maxChars - answerText(header).length - sectionLead('changed') - reserve };
|
|
604
|
+
const changed = shownRegions(file.plan, budget, maxChars).join('\n');
|
|
605
|
+
return textAnswer(answerText(header, [sectionText('changed', changed)]), { ...head, changed });
|
|
558
606
|
}
|
|
559
|
-
const listed:
|
|
560
|
-
const data:
|
|
607
|
+
const listed: ListedFile[] = [];
|
|
608
|
+
const data: { edits: number; replacements: number; disk: DiskState; files: ListedFile[]; filesNotListed?: number; changed: string } = {
|
|
561
609
|
edits: editCount,
|
|
562
610
|
replacements: files.reduce((sum, file) => sum + file.plan.replacements, 0),
|
|
611
|
+
disk,
|
|
563
612
|
files: listed,
|
|
564
613
|
changed: '',
|
|
565
614
|
};
|
|
566
|
-
const fits = (entry:
|
|
615
|
+
const fits = (entry: ListedFile) => {
|
|
567
616
|
listed.push(entry);
|
|
568
|
-
const fit =
|
|
617
|
+
const fit = manyHeadText(data).length + sectionLead('changed') <= maxChars - reserve;
|
|
569
618
|
listed.pop();
|
|
570
619
|
return fit;
|
|
571
620
|
};
|
|
@@ -574,7 +623,7 @@ export function editReceipt(tool: EditTool, files: StoredFile[], editCount: numb
|
|
|
574
623
|
let notListed = 0;
|
|
575
624
|
for (const [i, file] of files.entries()) {
|
|
576
625
|
const notes = notesOf(file);
|
|
577
|
-
const bare = {
|
|
626
|
+
const bare: ListedFile = {
|
|
578
627
|
path: file.path,
|
|
579
628
|
size: file.plan.bytes.length,
|
|
580
629
|
replacements: file.plan.replacements,
|
|
@@ -597,22 +646,22 @@ export function editReceipt(tool: EditTool, files: StoredFile[], editCount: numb
|
|
|
597
646
|
if (notes.length && !('note' in entry)) notesLeftOut++;
|
|
598
647
|
if (!('edits' in entry)) editsLeftOut++;
|
|
599
648
|
}
|
|
600
|
-
const budget = { left: maxChars -
|
|
649
|
+
const budget = { left: maxChars - manyHeadText(data).length - sectionLead('changed') - reserve };
|
|
601
650
|
const sections: string[] = [];
|
|
602
651
|
let unshown = 0;
|
|
603
652
|
for (const file of files.slice(0, listed.length)) {
|
|
604
|
-
const heading =
|
|
653
|
+
const heading = shownValue(file.path).length + 1 + (sections.length ? 2 : 0);
|
|
605
654
|
if (heading >= budget.left) {
|
|
606
655
|
unshown++;
|
|
607
656
|
continue;
|
|
608
657
|
}
|
|
609
658
|
budget.left -= heading;
|
|
610
|
-
sections.push(`${file.path}\n${shownRegions(file.plan, budget, maxChars).join('\n')}`);
|
|
659
|
+
sections.push(`${shownValue(file.path)}\n${shownRegions(file.plan, budget, maxChars).join('\n')}`);
|
|
611
660
|
}
|
|
612
661
|
const last = filesLeftOut(maxChars, files.length, { notListed, unshown, notes: notesLeftOut, edits: editsLeftOut });
|
|
613
662
|
if (last !== null) sections.push(last);
|
|
614
663
|
data.changed = sections.join('\n\n');
|
|
615
|
-
return data;
|
|
664
|
+
return textAnswer(answerText([manyHeadText(data)], [sectionText('changed', data.changed)]), data);
|
|
616
665
|
}
|
|
617
666
|
|
|
618
667
|
const capitalized = (value: string) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
@@ -47,7 +47,9 @@ import type { FileHandle } from 'node:fs/promises';
|
|
|
47
47
|
import {
|
|
48
48
|
type CheckedDir,
|
|
49
49
|
type MountView,
|
|
50
|
+
LEAVES_MOUNT,
|
|
50
51
|
NONBLOCK,
|
|
52
|
+
NOT_A_DIRECTORY,
|
|
51
53
|
NOT_FOLLOWED,
|
|
52
54
|
OUTSIDE_PARENT,
|
|
53
55
|
ROOT_REPLACED,
|
|
@@ -58,7 +60,6 @@ import {
|
|
|
58
60
|
leadsInto,
|
|
59
61
|
nameOf,
|
|
60
62
|
coversLanding,
|
|
61
|
-
namesNestedPlace,
|
|
62
63
|
nestedAtReal,
|
|
63
64
|
parentOf,
|
|
64
65
|
} from './observe.js';
|
|
@@ -232,7 +233,7 @@ export async function writeContained(
|
|
|
232
233
|
createMode?: number,
|
|
233
234
|
): Promise<{ perm: number; widenRefused: boolean; modeKept: boolean }> {
|
|
234
235
|
const checked = await parentFor(view, rootReal, rel, true);
|
|
235
|
-
if (checked.kind !== 'checked') throw new EffectFailed(
|
|
236
|
+
if (checked.kind !== 'checked') throw new EffectFailed(NOT_A_DIRECTORY, false);
|
|
236
237
|
const parent = checked.dir;
|
|
237
238
|
const root = checked.root;
|
|
238
239
|
const target = parent.at(nameOf(rel));
|
|
@@ -258,8 +259,16 @@ export async function writeContained(
|
|
|
258
259
|
touched = true;
|
|
259
260
|
return handle;
|
|
260
261
|
} catch (err) {
|
|
261
|
-
// O_EXCL refuses any entry: a file, a directory or a link
|
|
262
|
-
|
|
262
|
+
// O_EXCL refuses any entry: a file, a directory or a link, one that
|
|
263
|
+
// leads nowhere included, which a followed observation reads as absent.
|
|
264
|
+
if (errno(err) === 'EEXIST') {
|
|
265
|
+
const link = (await lstat(target).catch(() => null))?.isSymbolicLink() === true;
|
|
266
|
+
const leads = link ? await stat(target).then(() => 'somewhere', (e: unknown) => errno(e)) : null;
|
|
267
|
+
throw new EffectFailed(leads === 'ENOENT' || leads === 'ENOTDIR'
|
|
268
|
+
? 'a symlink that leads nowhere is at this path, and a push makes a file only where nothing is, forced or not; '
|
|
269
|
+
+ 'whoever runs this host can remove the link or make it lead to a file, and a materialize then writes it'
|
|
270
|
+
: 'something appeared at this path since it was checked', false);
|
|
271
|
+
}
|
|
263
272
|
throw new EffectFailed(`cannot create the file (${errno(err) ?? message(err)})`, false);
|
|
264
273
|
}
|
|
265
274
|
};
|
|
@@ -385,11 +394,11 @@ export async function writeContained(
|
|
|
385
394
|
* the link is what's refused. The opened file's check (checkOpened) asks
|
|
386
395
|
* it, and so does a create, before anything is made.
|
|
387
396
|
*/
|
|
388
|
-
async function refusedLanding(view: MountView, rootReal: string, rel: string, real: string): Promise<string | null> {
|
|
389
|
-
const leaves = view.followSymlinks ?
|
|
397
|
+
export async function refusedLanding(view: MountView, rootReal: string, rel: string, real: string): Promise<string | null> {
|
|
398
|
+
const leaves = view.followSymlinks ? LEAVES_MOUNT : OUTSIDE_PARENT;
|
|
390
399
|
if (!contained(rootReal, real)) return leaves;
|
|
391
|
-
const holder = nestedAtReal(real, view.nested);
|
|
392
|
-
if (holder) return
|
|
400
|
+
const holder = await nestedAtReal(real, view.nested, { name: view.name, rootReal });
|
|
401
|
+
if (holder) return holder.names(false) ? leadsInto(view.name, rel, holder) : view.followSymlinks ? leaves : NOT_FOLLOWED;
|
|
393
402
|
if (!(await coversLanding(view, rootReal, real, rel))) return view.followSymlinks ? leaves : NOT_FOLLOWED;
|
|
394
403
|
return null;
|
|
395
404
|
}
|
|
@@ -566,15 +575,15 @@ export async function unlinkContained(view: MountView, rootReal: string, rel: st
|
|
|
566
575
|
// The link itself is what is removed; a followed one must still lie inside.
|
|
567
576
|
if (!view.followSymlinks) throw new EffectFailed(NOT_FOLLOWED, false);
|
|
568
577
|
const real = await realpath(target).catch(() => null);
|
|
569
|
-
if (real === null || !contained(rootReal, real)) throw new EffectFailed(
|
|
578
|
+
if (real === null || !contained(rootReal, real)) throw new EffectFailed(LEAVES_MOUNT, false);
|
|
570
579
|
// One leading into a nested mount's directory is that mount's: the link
|
|
571
580
|
// and the file it leads to are left as they are. Where that mount's
|
|
572
581
|
// include leaves the place out, it's no mount's, and the link leaves this
|
|
573
582
|
// one (namesNestedPlace).
|
|
574
|
-
const holder = nestedAtReal(real, view.nested);
|
|
583
|
+
const holder = await nestedAtReal(real, view.nested, { name: view.name, rootReal });
|
|
575
584
|
if (holder) {
|
|
576
|
-
const directory = holder.
|
|
577
|
-
throw new EffectFailed(
|
|
585
|
+
const directory = holder.judgedByInclude && await stat(real).then((s) => s.isDirectory(), () => false);
|
|
586
|
+
throw new EffectFailed(holder.names(directory) ? leadsInto(view.name, rel, holder) : LEAVES_MOUNT, false);
|
|
578
587
|
}
|
|
579
588
|
const through = await stat(real, { bigint: true }).catch(() => null);
|
|
580
589
|
if (through === null) throw new EffectFailed(CHANGED, false);
|
|
@@ -586,7 +595,7 @@ export async function unlinkContained(view: MountView, rootReal: string, rel: st
|
|
|
586
595
|
if (!through.isFile()) throw new EffectFailed(through.isDirectory() ? 'a symlink to a directory, not walked' : 'not a regular file', false);
|
|
587
596
|
// One leading to a file this mount's own include leaves out leaves the
|
|
588
597
|
// mount too, and that file isn't read for a hash (coversLanding).
|
|
589
|
-
if (!(await coversLanding(view, rootReal, real, rel))) throw new EffectFailed(
|
|
598
|
+
if (!(await coversLanding(view, rootReal, real, rel))) throw new EffectFailed(LEAVES_MOUNT, false);
|
|
590
599
|
file = through;
|
|
591
600
|
} else if (info.isDirectory()) {
|
|
592
601
|
throw new EffectFailed('a directory', false);
|