@yanlinglabs/winter-agent-runtime 0.0.27
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/LICENSE +21 -0
- package/NOTICE +41 -0
- package/README.md +64 -0
- package/dist/checkpoint/file-history.d.ts +81 -0
- package/dist/checkpoint/rewind.d.ts +55 -0
- package/dist/checkpoint/seam.d.ts +47 -0
- package/dist/checkpoint/sink.d.ts +66 -0
- package/dist/commands/builtins-listing.d.ts +40 -0
- package/dist/commands/resolver.d.ts +103 -0
- package/dist/commands/seam.d.ts +53 -0
- package/dist/compaction/controller.d.ts +23 -0
- package/dist/compaction/retention.d.ts +35 -0
- package/dist/compaction/seam.d.ts +115 -0
- package/dist/compaction/summarizer.d.ts +79 -0
- package/dist/context/agent-listing.d.ts +39 -0
- package/dist/context/assembler.d.ts +46 -0
- package/dist/context/attachments.d.ts +104 -0
- package/dist/context/dynamic-sections.d.ts +31 -0
- package/dist/context/git-fixture.d.ts +18 -0
- package/dist/context/git-status.d.ts +16 -0
- package/dist/context/imports.d.ts +22 -0
- package/dist/context/injection.d.ts +53 -0
- package/dist/context/memory-key.d.ts +46 -0
- package/dist/context/memory.d.ts +28 -0
- package/dist/context/minimal-prompt.d.ts +5 -0
- package/dist/context/output-styles.d.ts +68 -0
- package/dist/context/plan-mode.d.ts +29 -0
- package/dist/context/request-layout.d.ts +138 -0
- package/dist/context/rules.d.ts +63 -0
- package/dist/context/seam.d.ts +136 -0
- package/dist/context/tool-epoch.d.ts +118 -0
- package/dist/context/winter-code-preset.d.ts +39 -0
- package/dist/context/winter-md.d.ts +81 -0
- package/dist/embedded-host.d.ts +48 -0
- package/dist/embedded-host.js +155 -0
- package/dist/embedded-protocol.d.ts +44 -0
- package/dist/embedded-worker.d.ts +1 -0
- package/dist/embedded-worker.js +74 -0
- package/dist/embedded.d.ts +34 -0
- package/dist/embedded.js +9 -0
- package/dist/engine.d.ts +1298 -0
- package/dist/hooks/additional-context.d.ts +21 -0
- package/dist/hooks/bounds.d.ts +6 -0
- package/dist/hooks/bridge-invoker.d.ts +3 -0
- package/dist/hooks/command-invoker.d.ts +52 -0
- package/dist/hooks/from-config.d.ts +31 -0
- package/dist/hooks/hook-stage.d.ts +25 -0
- package/dist/hooks/input-validator.d.ts +6 -0
- package/dist/hooks/reducer.d.ts +74 -0
- package/dist/hooks/registry.d.ts +33 -0
- package/dist/hooks/runner.d.ts +105 -0
- package/dist/index-584yahed.js +6037 -0
- package/dist/index-97t2rmtf.js +42 -0
- package/dist/index-9qgkpv56.js +27183 -0
- package/dist/index-bef62z3r.js +437 -0
- package/dist/index-rkhh0457.js +187 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +353 -0
- package/dist/main.d.ts +1 -0
- package/dist/mcp/client.d.ts +105 -0
- package/dist/mcp/control-seam.d.ts +25 -0
- package/dist/mcp/control.d.ts +5 -0
- package/dist/mcp/elicitation.d.ts +35 -0
- package/dist/mcp/env.d.ts +12 -0
- package/dist/mcp/lifecycle.d.ts +142 -0
- package/dist/mcp/output-cap.d.ts +15 -0
- package/dist/mcp/state.d.ts +24 -0
- package/dist/mcp/test-fixtures.d.ts +88 -0
- package/dist/mcp/transports/__fixtures__/stdio-server.d.ts +1 -0
- package/dist/mcp/transports/http.d.ts +5 -0
- package/dist/mcp/transports/sdk.d.ts +5 -0
- package/dist/mcp/transports/sse.d.ts +3 -0
- package/dist/mcp/transports/stdio.d.ts +35 -0
- package/dist/mcp/winter-server.d.ts +2 -0
- package/dist/messaging/reference-adapter.d.ts +88 -0
- package/dist/messaging/router.d.ts +8 -0
- package/dist/paths/project-dir-name.d.ts +2 -0
- package/dist/paths/temp.d.ts +25 -0
- package/dist/permissions/approvals.d.ts +107 -0
- package/dist/permissions/auto/caches.d.ts +53 -0
- package/dist/permissions/auto/config.d.ts +37 -0
- package/dist/permissions/auto/engine.d.ts +74 -0
- package/dist/permissions/auto/envelope.d.ts +45 -0
- package/dist/permissions/auto/inheritance.d.ts +27 -0
- package/dist/permissions/edit-recognition.d.ts +30 -0
- package/dist/permissions/evaluator.d.ts +284 -0
- package/dist/permissions/file-rules.d.ts +384 -0
- package/dist/permissions/grammar.d.ts +113 -0
- package/dist/permissions/paths.d.ts +32 -0
- package/dist/permissions/policy-state.d.ts +64 -0
- package/dist/permissions/prompt-stage.d.ts +3 -0
- package/dist/permissions/protected.d.ts +54 -0
- package/dist/permissions/ruleset.d.ts +134 -0
- package/dist/permissions/shell-structure.d.ts +41 -0
- package/dist/plugins/bundle.d.ts +100 -0
- package/dist/plugins/installed.d.ts +30 -0
- package/dist/plugins/loader.d.ts +56 -0
- package/dist/plugins/manifest.d.ts +115 -0
- package/dist/production-wiring.d.ts +340 -0
- package/dist/protocol/channel.d.ts +22 -0
- package/dist/provider/advisor-route.d.ts +47 -0
- package/dist/provider/bridge.d.ts +124 -0
- package/dist/provider/classifier/model-classifier.d.ts +82 -0
- package/dist/provider/classifier/prompt.d.ts +62 -0
- package/dist/provider/classifier/verdict-schema.d.ts +83 -0
- package/dist/provider/credential-api.d.ts +160 -0
- package/dist/provider/family-listing.d.ts +27 -0
- package/dist/provider/first-party.d.ts +4 -0
- package/dist/provider/keychain-store.d.ts +59 -0
- package/dist/provider/lean-prompt.d.ts +7 -0
- package/dist/provider/mock.d.ts +55 -0
- package/dist/provider/scenario-fake.d.ts +96 -0
- package/dist/provider/selection.d.ts +115 -0
- package/dist/provider/session-provider.d.ts +426 -0
- package/dist/provider/slots.d.ts +120 -0
- package/dist/provider/stream-frames.d.ts +25 -0
- package/dist/provider/tool-secret.d.ts +57 -0
- package/dist/rpc/bridge.d.ts +14 -0
- package/dist/rpc/mcp-control.d.ts +26 -0
- package/dist/runtime.d.ts +14 -0
- package/dist/sandbox/profile.d.ts +249 -0
- package/dist/sandbox/spawn.d.ts +139 -0
- package/dist/settings/env-filter.d.ts +52 -0
- package/dist/settings/loaders/hooks.d.ts +44 -0
- package/dist/settings/loaders/mcp-config.d.ts +83 -0
- package/dist/settings/loaders/plugin-mcp.d.ts +3 -0
- package/dist/settings/loaders/strict-plugin-only.d.ts +13 -0
- package/dist/settings/resolve.d.ts +2 -0
- package/dist/settings/sources.d.ts +2 -0
- package/dist/settings/trust.d.ts +36 -0
- package/dist/skills/attachment.d.ts +25 -0
- package/dist/skills/frontmatter.d.ts +64 -0
- package/dist/skills/index.d.ts +16 -0
- package/dist/skills/listing.d.ts +89 -0
- package/dist/skills/loader.d.ts +104 -0
- package/dist/skills/option.d.ts +68 -0
- package/dist/skills/permission-rules.d.ts +21 -0
- package/dist/skills/runtime.d.ts +21 -0
- package/dist/skills/store.d.ts +163 -0
- package/dist/store/continuation-attach.d.ts +44 -0
- package/dist/store/dialect.d.ts +526 -0
- package/dist/store/provider-state.d.ts +188 -0
- package/dist/store/resume.d.ts +92 -0
- package/dist/structured/ajv-seam.d.ts +7 -0
- package/dist/structured/descriptor.d.ts +9 -0
- package/dist/structured/seam.d.ts +51 -0
- package/dist/structured/validator.d.ts +22 -0
- package/dist/subagents/activity.d.ts +13 -0
- package/dist/subagents/availability.d.ts +30 -0
- package/dist/subagents/builtin-agents.d.ts +37 -0
- package/dist/subagents/child-engine.d.ts +198 -0
- package/dist/subagents/child-handle.d.ts +344 -0
- package/dist/subagents/definitions.d.ts +189 -0
- package/dist/subagents/fork.d.ts +55 -0
- package/dist/subagents/git-root.d.ts +1 -0
- package/dist/subagents/limits.d.ts +28 -0
- package/dist/subagents/notification-queue.d.ts +233 -0
- package/dist/subagents/plugin-agents.d.ts +5 -0
- package/dist/subagents/policy.d.ts +46 -0
- package/dist/subagents/register-default-factory.d.ts +66 -0
- package/dist/subagents/resolution.d.ts +56 -0
- package/dist/subagents/restore.d.ts +9 -0
- package/dist/subagents/roster.d.ts +17 -0
- package/dist/subagents/test-fakes.d.ts +12 -0
- package/dist/subagents/tool-pools.d.ts +69 -0
- package/dist/subagents/watchdog.d.ts +13 -0
- package/dist/subagents/workspace.d.ts +27 -0
- package/dist/testing.d.ts +5 -0
- package/dist/testing.js +194 -0
- package/dist/tools/background-tasks.d.ts +10 -0
- package/dist/tools/descriptors/_shared.d.ts +34 -0
- package/dist/tools/descriptors/advisor.d.ts +1 -0
- package/dist/tools/descriptors/agent.d.ts +47 -0
- package/dist/tools/descriptors/artifact.d.ts +1 -0
- package/dist/tools/descriptors/ask-user-question.d.ts +1 -0
- package/dist/tools/descriptors/bash.d.ts +20 -0
- package/dist/tools/descriptors/claude-design.d.ts +1 -0
- package/dist/tools/descriptors/cron-create.d.ts +1 -0
- package/dist/tools/descriptors/cron-delete.d.ts +1 -0
- package/dist/tools/descriptors/cron-list.d.ts +1 -0
- package/dist/tools/descriptors/edit.d.ts +1 -0
- package/dist/tools/descriptors/end-conversation.d.ts +1 -0
- package/dist/tools/descriptors/enter-plan-mode.d.ts +1 -0
- package/dist/tools/descriptors/enter-worktree.d.ts +1 -0
- package/dist/tools/descriptors/exit-plan-mode.d.ts +1 -0
- package/dist/tools/descriptors/exit-worktree.d.ts +1 -0
- package/dist/tools/descriptors/glob.d.ts +1 -0
- package/dist/tools/descriptors/grep.d.ts +1 -0
- package/dist/tools/descriptors/index.d.ts +59 -0
- package/dist/tools/descriptors/list-agents.d.ts +1 -0
- package/dist/tools/descriptors/list-mcp-resources-tool.d.ts +1 -0
- package/dist/tools/descriptors/lsp.d.ts +1 -0
- package/dist/tools/descriptors/monitor.d.ts +1 -0
- package/dist/tools/descriptors/notebook-edit.d.ts +1 -0
- package/dist/tools/descriptors/powershell.d.ts +1 -0
- package/dist/tools/descriptors/projects.d.ts +1 -0
- package/dist/tools/descriptors/propose-goal.d.ts +1 -0
- package/dist/tools/descriptors/propose-skills.d.ts +1 -0
- package/dist/tools/descriptors/push-notification.d.ts +1 -0
- package/dist/tools/descriptors/read-mcp-resource-dir-tool.d.ts +1 -0
- package/dist/tools/descriptors/read-mcp-resource-tool.d.ts +1 -0
- package/dist/tools/descriptors/read-notifications.d.ts +1 -0
- package/dist/tools/descriptors/read.d.ts +1 -0
- package/dist/tools/descriptors/refresh-mcp-tools.d.ts +1 -0
- package/dist/tools/descriptors/remote-trigger.d.ts +1 -0
- package/dist/tools/descriptors/repl.d.ts +1 -0
- package/dist/tools/descriptors/report-findings.d.ts +1 -0
- package/dist/tools/descriptors/schedule-wakeup.d.ts +1 -0
- package/dist/tools/descriptors/send-feedback.d.ts +1 -0
- package/dist/tools/descriptors/send-message.d.ts +1 -0
- package/dist/tools/descriptors/send-user-file.d.ts +1 -0
- package/dist/tools/descriptors/share-onboarding-guide.d.ts +1 -0
- package/dist/tools/descriptors/show-onboarding-role-picker.d.ts +1 -0
- package/dist/tools/descriptors/skill.d.ts +1 -0
- package/dist/tools/descriptors/structured-output.d.ts +1 -0
- package/dist/tools/descriptors/task-create.d.ts +1 -0
- package/dist/tools/descriptors/task-get.d.ts +1 -0
- package/dist/tools/descriptors/task-list.d.ts +1 -0
- package/dist/tools/descriptors/task-output.d.ts +1 -0
- package/dist/tools/descriptors/task-stop.d.ts +1 -0
- package/dist/tools/descriptors/task-update.d.ts +1 -0
- package/dist/tools/descriptors/todo-write.d.ts +1 -0
- package/dist/tools/descriptors/tool-search.d.ts +1 -0
- package/dist/tools/descriptors/wait-for-mcp-servers.d.ts +1 -0
- package/dist/tools/descriptors/web-fetch.d.ts +8 -0
- package/dist/tools/descriptors/web-search.d.ts +15 -0
- package/dist/tools/descriptors/winter-list-agents.d.ts +1 -0
- package/dist/tools/descriptors/winter-send-message.d.ts +1 -0
- package/dist/tools/descriptors/workflow.d.ts +1 -0
- package/dist/tools/descriptors/write.d.ts +1 -0
- package/dist/tools/impl/_caller.d.ts +14 -0
- package/dist/tools/impl/_domains.d.ts +25 -0
- package/dist/tools/impl/_exa-client.d.ts +122 -0
- package/dist/tools/impl/_exa-session-client.d.ts +23 -0
- package/dist/tools/impl/_inner-model.d.ts +135 -0
- package/dist/tools/impl/_search-budget.d.ts +36 -0
- package/dist/tools/impl/_web-fetch-cache.d.ts +37 -0
- package/dist/tools/impl/_web-fetch-html.d.ts +26 -0
- package/dist/tools/impl/_web-fetch-net.d.ts +99 -0
- package/dist/tools/impl/_web-search-assembler.d.ts +57 -0
- package/dist/tools/impl/advisor.d.ts +37 -0
- package/dist/tools/impl/agent.d.ts +10 -0
- package/dist/tools/impl/ask-user-question.d.ts +5 -0
- package/dist/tools/impl/background-task-runtime.d.ts +272 -0
- package/dist/tools/impl/bash.d.ts +78 -0
- package/dist/tools/impl/cron.d.ts +11 -0
- package/dist/tools/impl/edit.d.ts +1 -0
- package/dist/tools/impl/enter-plan-mode.d.ts +4 -0
- package/dist/tools/impl/enter-worktree.d.ts +25 -0
- package/dist/tools/impl/exit-plan-mode.d.ts +4 -0
- package/dist/tools/impl/exit-worktree.d.ts +4 -0
- package/dist/tools/impl/glob.d.ts +1 -0
- package/dist/tools/impl/grep.d.ts +19 -0
- package/dist/tools/impl/index.d.ts +37 -0
- package/dist/tools/impl/list-agents.d.ts +7 -0
- package/dist/tools/impl/list-mcp-resources-tool.d.ts +9 -0
- package/dist/tools/impl/monitor.d.ts +66 -0
- package/dist/tools/impl/notebook-edit.d.ts +1 -0
- package/dist/tools/impl/push-notification.d.ts +4 -0
- package/dist/tools/impl/read-ladder.d.ts +25 -0
- package/dist/tools/impl/read-mcp-resource-dir-tool.d.ts +9 -0
- package/dist/tools/impl/read-mcp-resource-tool.d.ts +9 -0
- package/dist/tools/impl/read-notifications.d.ts +5 -0
- package/dist/tools/impl/read.d.ts +44 -0
- package/dist/tools/impl/refresh-mcp-tools.d.ts +8 -0
- package/dist/tools/impl/report-findings.d.ts +1 -0
- package/dist/tools/impl/schedule-wakeup.d.ts +2 -0
- package/dist/tools/impl/send-message.d.ts +7 -0
- package/dist/tools/impl/skill.d.ts +5 -0
- package/dist/tools/impl/task-graph.d.ts +1 -0
- package/dist/tools/impl/task-output.d.ts +16 -0
- package/dist/tools/impl/task-stop.d.ts +11 -0
- package/dist/tools/impl/todo-write.d.ts +8 -0
- package/dist/tools/impl/tool-search.d.ts +4 -0
- package/dist/tools/impl/wait-for-mcp-servers.d.ts +29 -0
- package/dist/tools/impl/web-fetch.d.ts +36 -0
- package/dist/tools/impl/web-search.d.ts +30 -0
- package/dist/tools/impl/workflow.d.ts +5 -0
- package/dist/tools/impl/write.d.ts +8 -0
- package/dist/tools/paths-seam.d.ts +6 -0
- package/dist/tools/read-state.d.ts +12 -0
- package/dist/tools/registry.d.ts +423 -0
- package/dist/tools/task-graph-store.d.ts +61 -0
- package/dist/toolsearch/aliases.d.ts +26 -0
- package/dist/toolsearch/exposure.d.ts +30 -0
- package/dist/toolsearch/ranking.d.ts +6 -0
- package/dist/toolsearch/search.d.ts +45 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/web/fetchable-url.d.ts +28 -0
- package/dist/web/preapproved-hosts.d.ts +52 -0
- package/dist/web/private-address.d.ts +55 -0
- package/dist/web/session-runtime.d.ts +86 -0
- package/dist/workflows/bridge.d.ts +87 -0
- package/dist/workflows/budget.d.ts +24 -0
- package/dist/workflows/host-registry.d.ts +142 -0
- package/dist/workflows/journal.d.ts +29 -0
- package/dist/workflows/meta.d.ts +45 -0
- package/dist/workflows/registry.d.ts +24 -0
- package/dist/workflows/runtime.d.ts +254 -0
- package/dist/workflows/sandbox.d.ts +49 -0
- package/dist/workflows/script-api.d.ts +58 -0
- package/dist/workflows/seam.d.ts +92 -0
- package/dist/workflows/semaphore.d.ts +16 -0
- package/dist/workflows/store.d.ts +177 -0
- package/dist/workflows/subprocess-entry.d.ts +38 -0
- package/dist/workflows/subprocess-entry.js +14 -0
- package/dist/workflows/transcript.d.ts +56 -0
- package/dist/workflows/types.d.ts +84 -0
- package/dist/workflows/worker-harness.d.ts +45 -0
- package/package.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yanlingLabs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
NOTICE
|
|
2
|
+
======
|
|
3
|
+
|
|
4
|
+
Third-party attributions for the Winter agent SDK.
|
|
5
|
+
|
|
6
|
+
This file records material that Winter DERIVED FROM third-party artifacts. Winter copies no source
|
|
7
|
+
code from any of them; what it takes is protocol facts — endpoint URLs, form-field names, client
|
|
8
|
+
identifiers and scope strings — which it needs in order to speak to a vendor's service at all. Each
|
|
9
|
+
entry names the exact commit the values were read at, so the derivation is re-checkable.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
-------------------------------------------------------------------------------
|
|
13
|
+
xai-org/grok-build
|
|
14
|
+
-------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
Repository: https://github.com/xai-org/grok-build
|
|
17
|
+
Commit: 72a61251fcffb464bcc687aeb5a998e5a98ec0c9
|
|
18
|
+
License: Apache License, Version 2.0
|
|
19
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
20
|
+
Copyright: Copyright 2023-2026 SpaceXAI
|
|
21
|
+
|
|
22
|
+
Winter's `xai-oauth` provider derives the following constants and request shapes from this
|
|
23
|
+
repository's authentication module, in order to perform its own OAuth 2.0 device authorization
|
|
24
|
+
grant (RFC 8628) against xAI's public, secret-less OAuth client:
|
|
25
|
+
|
|
26
|
+
- the public OAuth client identifier
|
|
27
|
+
- the OAuth issuer, device-authorization endpoint and token endpoint
|
|
28
|
+
- the requested scope set
|
|
29
|
+
- the name of the form field the flow carries a client identity in
|
|
30
|
+
- the shape (field names) of the device-authorization and token requests
|
|
31
|
+
|
|
32
|
+
No source code from this repository is copied into Winter, and no part of Winter is a derivative
|
|
33
|
+
work of it. The derivation is recorded, with per-value line citations, in:
|
|
34
|
+
|
|
35
|
+
packages/conformance/compat/xai/grok-build/derived-shapes-p6b-xai.md
|
|
36
|
+
|
|
37
|
+
Winter identifies ITSELF in that flow. It sends its own `User-Agent` (`winter-agent-sdk/<version>`)
|
|
38
|
+
and its own name in the flow's identity field, and it does not send xAI's product-identity or
|
|
39
|
+
telemetry headers. Winter is not affiliated with or endorsed by SpaceXAI, and "Grok" and "Grok Build"
|
|
40
|
+
are the marks of their owner; they appear here and in the capture solely to identify the artifact
|
|
41
|
+
these values were derived from.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# `@yanlinglabs/winter-agent-runtime`
|
|
2
|
+
|
|
3
|
+
Winter's agent engine: the turn loop, the built-in tools, the session store and the provider wiring
|
|
4
|
+
that the compiled `winter` binary runs. Most hosts never install this package — they install
|
|
5
|
+
`@yanlinglabs/winter-agent-sdk`, whose `query()` spawns that binary.
|
|
6
|
+
|
|
7
|
+
This package is for a host that wants to run sessions **in its own process** instead. It is Bun-only.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
This package is published to **two registries**, and which one you want depends on who you are.
|
|
12
|
+
|
|
13
|
+
### From public npm (anyone)
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install @yanlinglabs/winter-agent-runtime
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Nothing else is needed: the `@yanlinglabs` scope is public on npm.
|
|
20
|
+
|
|
21
|
+
### From GitHub Packages (the `yanlingLabs` org)
|
|
22
|
+
|
|
23
|
+
GitHub Packages needs the scope pointed at it and an authenticated read, even for a public package.
|
|
24
|
+
In your project's `.npmrc`:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
@yanlinglabs:registry=https://npm.pkg.github.com
|
|
28
|
+
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
…with `GITHUB_TOKEN` in the environment — a personal access token carrying `read:packages`, never a
|
|
32
|
+
literal in the file. Then `npm install @yanlinglabs/winter-agent-runtime` as usual.
|
|
33
|
+
|
|
34
|
+
**The published packages contain COMPILED OUTPUT ONLY.** Each tarball ships `dist/` — the bundled
|
|
35
|
+
JavaScript a consumer imports and the `.d.ts` declarations their type-checker reads — plus
|
|
36
|
+
`README.md`, `NOTICE` and `LICENSE`. The TypeScript sources live at
|
|
37
|
+
<https://github.com/yanlingLabs/winter-agent-sdk>, which is where to read them, file an issue, or send
|
|
38
|
+
a patch.
|
|
39
|
+
|
|
40
|
+
This package, `@yanlinglabs/winter-agent-sdk` and its platform binary package are released together
|
|
41
|
+
at one version, and each pins the others exactly.
|
|
42
|
+
|
|
43
|
+
## Embedding a session
|
|
44
|
+
|
|
45
|
+
The runtime keeps per-process state (its tool registry, MCP executors, background-task table), so
|
|
46
|
+
each session needs its own JavaScript realm: run one session per Bun `Worker`.
|
|
47
|
+
|
|
48
|
+
- `@yanlinglabs/winter-agent-runtime/embedded-host` — `spawnEmbeddedWorker(...)` constructs the Worker
|
|
49
|
+
and returns a `SpawnedRuntimeProcess`. Hand it to `query()` through `Options.spawnClaudeCodeProcess`.
|
|
50
|
+
The frames on the wire are exactly the ones the spawned binary writes. This module does not load
|
|
51
|
+
the engine, so it is safe to import on a host's main thread.
|
|
52
|
+
- `@yanlinglabs/winter-agent-runtime/embedded-worker` — the Worker entry. A compiled
|
|
53
|
+
(`bun build --compile`) host passes its own one-line worker file as an extra entrypoint and
|
|
54
|
+
constructs the Worker from that file's plain relative path.
|
|
55
|
+
- `@yanlinglabs/winter-agent-runtime/embedded` — `runEmbeddedSession(...)`, one session with every
|
|
56
|
+
process global (argv, env, stdio, exit) as a parameter.
|
|
57
|
+
- `@yanlinglabs/winter-agent-runtime/workflow-worker` — the Workflow tool's sandboxed worker entry,
|
|
58
|
+
for a host that routes its own binary's argv to it.
|
|
59
|
+
- `@yanlinglabs/winter-agent-runtime/version` — `RUNTIME_VERSION`, with no other imports. A host
|
|
60
|
+
should check that it equals the wrapper's `SDK_VERSION` before it runs a session.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT — see [`LICENSE`](./LICENSE), which ships in the published tarball.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** The directory name under `~/.winter`. One constant so a fixture and the sink cannot disagree. */
|
|
2
|
+
export declare const CHECKPOINT_DIRNAME = "file-history";
|
|
3
|
+
/** The private per-session record of intercepted mutations. */
|
|
4
|
+
export declare const CHECKPOINT_INDEX_FILENAME = "index.jsonl";
|
|
5
|
+
export type CheckpointRecordKind = "snapshot" | "delta";
|
|
6
|
+
export interface CheckpointRecord {
|
|
7
|
+
kind: CheckpointRecordKind;
|
|
8
|
+
/** The envelope this mutation belongs to -- the unit `rewind` restores to. */
|
|
9
|
+
userMessageUuid: string;
|
|
10
|
+
/** Absolute, resolved. */
|
|
11
|
+
path: string;
|
|
12
|
+
pathHash: string;
|
|
13
|
+
/** Which mutating tool announced it. Recorded for auditability; the rewind does not branch on it. */
|
|
14
|
+
tool: string;
|
|
15
|
+
at: string;
|
|
16
|
+
/**
|
|
17
|
+
* The blob version for a snapshot (`<path-hash>@v<version>`); for a delta, the snapshot version it
|
|
18
|
+
* follows. Counts SNAPSHOTS only, so the blob numbering is dense and `@v2` really is the second
|
|
19
|
+
* backup of that file rather than the second time it was touched.
|
|
20
|
+
*/
|
|
21
|
+
version: number;
|
|
22
|
+
/** The file did not exist at checkpoint time -- there are no bytes, and a rewind DELETES it. */
|
|
23
|
+
absent?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* `realpath(dirname(path))` at checkpoint time. Item (e)'s rule: a path whose parent no longer
|
|
26
|
+
* resolves where it did is REFUSED rather than restored -- otherwise a rewind follows a directory
|
|
27
|
+
* that has since become a link and writes the pre-image into somebody else's tree.
|
|
28
|
+
*
|
|
29
|
+
* KEPT ALONGSIDE the anchor pair below rather than replaced by it. It costs one string, it is
|
|
30
|
+
* checked independently, and removing a guard is never the safe direction -- it also keeps records
|
|
31
|
+
* written by an earlier build fully protected.
|
|
32
|
+
*
|
|
33
|
+
* **It is absent exactly when the parent did not exist at checkpoint time**, which is precisely the
|
|
34
|
+
* `absent: true` case whose rewind arm DELETES the file. That is why it cannot be the only
|
|
35
|
+
* path-identity guard: see `anchorPath`.
|
|
36
|
+
*/
|
|
37
|
+
parentRealPath?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The nearest ancestor directory that EXISTED at checkpoint time, as written (not realpath'd), plus
|
|
40
|
+
* its real path at that moment. Recorded for EVERY record, including one whose own parent did not
|
|
41
|
+
* exist yet -- a `Write` to a path the tool is about to `mkdir -p`.
|
|
42
|
+
*
|
|
43
|
+
* This is the fix for a demonstrated hole: with `parentRealPath` absent on exactly those records,
|
|
44
|
+
* the delete arm ran with NO path-identity check at all, so replacing the not-yet-existing
|
|
45
|
+
* directory with a symlink let a rewind `rmSync` a file the session had never touched. At rewind
|
|
46
|
+
* the anchor must still resolve to `anchorRealPath` AND no component between it and the target may
|
|
47
|
+
* have become a symlink.
|
|
48
|
+
*/
|
|
49
|
+
anchorPath?: string;
|
|
50
|
+
anchorRealPath?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function checkpointPathHash(absolutePath: string): string;
|
|
53
|
+
export declare function sessionCheckpointDir(home: string, sessionUuid: string): string;
|
|
54
|
+
export declare function blobName(pathHash: string, version: number): string;
|
|
55
|
+
/** `realpath` of the parent, or undefined when it cannot be resolved (the directory is gone). */
|
|
56
|
+
export declare function parentRealPathOf(absolutePath: string): string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* The nearest ancestor DIRECTORY of `absolutePath` that exists right now, with its real path.
|
|
59
|
+
* Walks upward until something resolves, so it answers even for a path several not-yet-created
|
|
60
|
+
* directories deep -- which is the whole point: a checkpoint taken before `mkdir -p` still gets a
|
|
61
|
+
* real anchor to verify against later.
|
|
62
|
+
*
|
|
63
|
+
* Returns undefined only if nothing up to the filesystem root resolves, which in practice means the
|
|
64
|
+
* volume itself is gone; the rewind then refuses rather than guessing.
|
|
65
|
+
*/
|
|
66
|
+
export declare function nearestExistingAncestor(absolutePath: string): {
|
|
67
|
+
anchorPath: string;
|
|
68
|
+
anchorRealPath: string;
|
|
69
|
+
} | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Reads the session's records, oldest first. A missing directory or file is an EMPTY history, never
|
|
72
|
+
* an error: `rewind` on a session that has mutated nothing must answer "nothing to rewind to", and
|
|
73
|
+
* a `dryRun` must not bring the directory into existence just by asking.
|
|
74
|
+
*
|
|
75
|
+
* A malformed line is skipped rather than fatal -- a truncated final line (a process killed
|
|
76
|
+
* mid-append) must not make every earlier checkpoint unreadable.
|
|
77
|
+
*/
|
|
78
|
+
export declare function readCheckpointIndex(home: string, sessionUuid: string): CheckpointRecord[];
|
|
79
|
+
export declare function appendCheckpointRecord(home: string, sessionUuid: string, record: CheckpointRecord): void;
|
|
80
|
+
/** The pre-image bytes, or undefined when the file does not exist / is not a regular file. */
|
|
81
|
+
export declare function readPreImage(absolutePath: string): Buffer | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { RewindFilesResult } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import { type CheckpointRecord } from "./file-history.js";
|
|
3
|
+
/**
|
|
4
|
+
* Line counts, Winter-defined and DISCLOSED: the pin declares `insertions`/`deletions` as numbers and
|
|
5
|
+
* defines no algorithm for them. This is a MULTISET (bag) difference -- for each distinct line, the
|
|
6
|
+
* surplus in one side over the other -- which is O(n+m), deterministic, and exact for the pure
|
|
7
|
+
* insert/delete edits a rewind actually undoes. A minimal-edit-script (LCS) count would be O(n*m)
|
|
8
|
+
* over arbitrary files, and a rewind must not become the slowest thing in a session.
|
|
9
|
+
*
|
|
10
|
+
* `insertions` = lines the rewind ADDS (present in the restored content, missing from the current);
|
|
11
|
+
* `deletions` = lines it REMOVES. Reported from the FILE's point of view, matching the direction a
|
|
12
|
+
* host renders as "+/-".
|
|
13
|
+
*/
|
|
14
|
+
export declare function countLineDelta(current: string[], restored: string[]): {
|
|
15
|
+
insertions: number;
|
|
16
|
+
deletions: number;
|
|
17
|
+
};
|
|
18
|
+
/** A trailing newline terminates the last line rather than starting an empty one. */
|
|
19
|
+
export declare function splitLines(content: Buffer | undefined): string[];
|
|
20
|
+
/**
|
|
21
|
+
* PATH-IDENTITY refusals: the recorded path no longer names the file the checkpoint was about, so a
|
|
22
|
+
* restore would write into -- or DELETE -- somebody else's tree.
|
|
23
|
+
*
|
|
24
|
+
* Three independent guards, all cheap, none removable:
|
|
25
|
+
*
|
|
26
|
+
* 1. the nearest ancestor that existed at checkpoint time must still resolve to the same real
|
|
27
|
+
* directory (`anchorPath`/`anchorRealPath`);
|
|
28
|
+
* 2. no component between that ancestor and the target may have become a symlink since;
|
|
29
|
+
* 3. the legacy immediate-parent check, kept because removing a guard is never the safe direction
|
|
30
|
+
* and because it still protects records written by an earlier build.
|
|
31
|
+
*
|
|
32
|
+
* Guards 1 and 2 exist because guard 3 alone was INERT ON EXACTLY THE RECORDS THE DELETE ARM ACTS
|
|
33
|
+
* ON: `parentRealPath` is absent precisely when the parent did not exist at checkpoint time, which
|
|
34
|
+
* is the `absent: true` case, which is the case `rmSync` services. Replacing the not-yet-created
|
|
35
|
+
* directory with a symlink then let a rewind delete a never-checkpointed file, silently.
|
|
36
|
+
*
|
|
37
|
+
* These are evaluated on a `dryRun` TOO -- see `rewindToCheckpoint` for why that is not the
|
|
38
|
+
* "previews do not reflect refusals" clause.
|
|
39
|
+
*/
|
|
40
|
+
export declare function describeRefusal(record: Pick<CheckpointRecord, "path" | "anchorPath" | "anchorRealPath" | "parentRealPath">): string | undefined;
|
|
41
|
+
export interface RewindOptions {
|
|
42
|
+
home: string;
|
|
43
|
+
sessionUuid: string;
|
|
44
|
+
userMessageUuid: string;
|
|
45
|
+
dryRun: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* T8 rider 25: the session's own writable roots (its `cwd` plus any `additionalDirectories`). A
|
|
48
|
+
* record naming a path outside every one of them is REFUSED -- see `isInsideSessionRoots`.
|
|
49
|
+
*
|
|
50
|
+
* REQUIRED, not optional-defaulting-to-unfenced: an omitted fence is exactly the state this rider
|
|
51
|
+
* closes, and a caller that genuinely wants no fence has to say so by passing `["/"]`.
|
|
52
|
+
*/
|
|
53
|
+
roots: readonly string[];
|
|
54
|
+
}
|
|
55
|
+
export declare function rewindToCheckpoint(opts: RewindOptions): RewindFilesResult;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { RewindFilesResult } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
/** The three mutating tools checkpointing intercepts, as one exported set so the engine's check and a lane's own fixtures cannot drift. */
|
|
3
|
+
export declare const CHECKPOINTED_TOOLS: readonly ["Write", "Edit", "NotebookEdit"];
|
|
4
|
+
export type CheckpointedTool = (typeof CHECKPOINTED_TOOLS)[number];
|
|
5
|
+
export declare function isCheckpointedTool(name: string): name is CheckpointedTool;
|
|
6
|
+
export interface CheckpointMutation {
|
|
7
|
+
path: string;
|
|
8
|
+
tool: CheckpointedTool;
|
|
9
|
+
/** The engine-minted id of the user envelope this mutation belongs to -- the unit `rewind` restores to. */
|
|
10
|
+
userMessageUuid: string;
|
|
11
|
+
sessionUuid: string;
|
|
12
|
+
}
|
|
13
|
+
export interface FileCheckpointSink {
|
|
14
|
+
/**
|
|
15
|
+
* Called BEFORE the mutation runs, once per candidate write path. A sink that throws does NOT stop
|
|
16
|
+
* the write: the engine treats a checkpoint failure the way it treats a store failure -- auxiliary,
|
|
17
|
+
* reported, never turn-fatal. That is a deliberate choice in the safe direction for the USER'S WORK
|
|
18
|
+
* (the edit they asked for still happens) and the unsafe one for undo, so a sink that cannot back
|
|
19
|
+
* up must say so loudly rather than failing silently.
|
|
20
|
+
*/
|
|
21
|
+
beforeMutation(req: CheckpointMutation): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Restores every tracked file to its state at `userMessageUuid`. `dryRun` previews without
|
|
24
|
+
* touching the filesystem -- and, per item (e), without populating `skippedLinks`.
|
|
25
|
+
*
|
|
26
|
+
* Returns `canRewind: false` with an `error` for an unknown/untracked id rather than throwing: the
|
|
27
|
+
* control request that reaches this is a host action, and "there is nothing to rewind to" is an
|
|
28
|
+
* answer, not a failure.
|
|
29
|
+
*/
|
|
30
|
+
rewind(userMessageUuid: string, opts?: {
|
|
31
|
+
dryRun?: boolean;
|
|
32
|
+
}): Promise<RewindFilesResult>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The spine's test double: an in-memory sink recording every intercepted mutation and answering
|
|
36
|
+
* `rewind` from a canned table. It touches no filesystem at all -- Lane K's real sink is what proves
|
|
37
|
+
* backup/restore.
|
|
38
|
+
*/
|
|
39
|
+
export declare function fakeFileCheckpointSink(opts?: {
|
|
40
|
+
mutations?: CheckpointMutation[];
|
|
41
|
+
results?: Record<string, RewindFilesResult>;
|
|
42
|
+
rewindCalls?: Array<{
|
|
43
|
+
userMessageUuid: string;
|
|
44
|
+
dryRun: boolean;
|
|
45
|
+
}>;
|
|
46
|
+
failBeforeMutation?: string;
|
|
47
|
+
}): FileCheckpointSink;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { FileCheckpointSink } from "./seam.js";
|
|
2
|
+
import { type CheckpointRecord } from "./file-history.js";
|
|
3
|
+
export { CHECKPOINT_DIRNAME, CHECKPOINT_INDEX_FILENAME } from "./file-history.js";
|
|
4
|
+
export interface FileCheckpointSinkOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The session this sink rewinds. REQUIRED, because `rewind(userMessageUuid)` carries no session of
|
|
7
|
+
* its own: checkpoints belong to a session (WS-11 §9's scope row), and a sink that guessed would
|
|
8
|
+
* let one session undo another's work.
|
|
9
|
+
*/
|
|
10
|
+
sessionUuid: string;
|
|
11
|
+
/**
|
|
12
|
+
* The resolved product root (`<PREFIX>HOME` || `~/<homeDirName>`), the directory this sink writes
|
|
13
|
+
* its backups and its index under. REQUIRED.
|
|
14
|
+
*
|
|
15
|
+
* P7a fix wave (item 5, whole-branch review M-5): it used to default to `resolveWinterHome(opts.env)`
|
|
16
|
+
* -- WITH NO BRAND -- which reads `WINTER_HOME` and `~/.winter`. Unreachable today (the sole
|
|
17
|
+
* production caller, `production-wiring.ts`, passes the session's own resolved root), but it is the
|
|
18
|
+
* same shape as I-1 one call site away from being live: a reuser's checkpoints would have been
|
|
19
|
+
* written into, and rewound from, WINTER's home. There is no brand-neutral default to fall back
|
|
20
|
+
* to, so the parameter is required rather than brand-threaded -- a caller that has a session at
|
|
21
|
+
* all has already resolved its root, and one that has not must not be given Winter's.
|
|
22
|
+
*
|
|
23
|
+
* Every test passes a mkdtemp root.
|
|
24
|
+
*/
|
|
25
|
+
home: string;
|
|
26
|
+
/**
|
|
27
|
+
* Resolves a RELATIVE candidate write path. `extractCandidateWritePaths` yields the path the tool
|
|
28
|
+
* call carried, which is usually but not always absolute -- and the backup identity is the hash of
|
|
29
|
+
* the ABSOLUTE path, so resolving late would file two spellings of one file as two histories.
|
|
30
|
+
*
|
|
31
|
+
* WS-23: REQUIRED -- it used to default to `process.cwd()`, which inside an embedded session's
|
|
32
|
+
* Worker is the host daemon's cwd, so a relative write path would have been filed under the wrong tree.
|
|
33
|
+
*/
|
|
34
|
+
cwd: string;
|
|
35
|
+
/**
|
|
36
|
+
* T8 rider 25 (SECURITY): extra roots the session was configured to write outside `cwd`
|
|
37
|
+
* (`RuntimeConfig.additionalDirectories`). `rewind` refuses a record naming a path outside `cwd`
|
|
38
|
+
* and these, so a tampered `index.jsonl` cannot become an arbitrary write or delete -- but a file
|
|
39
|
+
* the session GENUINELY edited in a granted directory must still restore, which is what this
|
|
40
|
+
* field carries. Omitted => `cwd` is the whole fence.
|
|
41
|
+
*/
|
|
42
|
+
additionalDirectories?: readonly string[];
|
|
43
|
+
/**
|
|
44
|
+
* Phase 5 Task 8 (riders 9/16): the session's durable transcript sink, so every checkpoint record
|
|
45
|
+
* is ALSO visible to a transcript reader (`store/dialect.ts`'s `file-history-snapshot` /
|
|
46
|
+
* `file-history-delta`). Lane K's concern 1 named exactly this cost of the private sidecar.
|
|
47
|
+
*
|
|
48
|
+
* A MIRROR, deliberately, and the sidecar remains this sink's own read authority -- see that
|
|
49
|
+
* module's own header for the two blockers that keep the retirement half of rider 16 open. The
|
|
50
|
+
* mirror is best-effort: a store failure NEVER fails the mutation it accompanies, matching
|
|
51
|
+
* `recordHookAudit`/`recordPermissionUpdate`'s established auxiliary-sink policy. A backup that
|
|
52
|
+
* exists with no transcript line still restores; a transcript line with no backup would be the
|
|
53
|
+
* dangerous direction, which is why the sidecar write stays first.
|
|
54
|
+
*/
|
|
55
|
+
persistence?: {
|
|
56
|
+
recordFileHistory?(record: CheckpointRecord): void | Promise<void>;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* P7a fix wave (item 5, M-5): RETAINED but now inert here -- its only reader was the brand-less
|
|
60
|
+
* `resolveWinterHome(opts.env)` default that `home` replaced. Kept on the options type because
|
|
61
|
+
* callers pass it and removing it would be a breaking change for no gain; a future reader of an
|
|
62
|
+
* env-derived value has a place to look.
|
|
63
|
+
*/
|
|
64
|
+
env?: Record<string, string | undefined>;
|
|
65
|
+
}
|
|
66
|
+
export declare function createFileCheckpointSink(opts: FileCheckpointSinkOptions): FileCheckpointSink;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FilesystemCommandResolver, SlashCommandInfo } from "./resolver.js";
|
|
2
|
+
/**
|
|
3
|
+
* The engine's own commands. DELIBERATELY ONE ENTRY: R5-14 ships `/compact [instructions]` and marks
|
|
4
|
+
* every other built-in capture-pending, and `CommandResolution`'s `builtin` arm is a single literal
|
|
5
|
+
* for the same reason. Adding one here without adding the engine branch would advertise a command
|
|
6
|
+
* that resolves to nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare const BUILTIN_SLASH_COMMANDS: readonly SlashCommandInfo[];
|
|
9
|
+
/**
|
|
10
|
+
* The full listing: built-ins, then whatever the resolver enumerates (skills, then command files
|
|
11
|
+
* project > user > plugin), first occurrence winning.
|
|
12
|
+
*
|
|
13
|
+
* THE INVARIANT, STATED EXACTLY: **for a given `cwd`**, every name listed here resolves at that same
|
|
14
|
+
* `cwd`, and to the producer this listing names. Two qualifications, both load-bearing:
|
|
15
|
+
*
|
|
16
|
+
* - **The `cwd` is part of the statement** (fix round 2, Minor B). Command files are discovered by a
|
|
17
|
+
* parent-walk from the cwd, so the enumeration genuinely differs between cwds, and
|
|
18
|
+
* `FilesystemCommandResolver.list()` defaults to the resolver's CONSTRUCTION cwd while
|
|
19
|
+
* `resolve()` always uses the live one it is handed. A caller that lists at one cwd and resolves
|
|
20
|
+
* at another is comparing two different namespaces, and the invariant says nothing about that
|
|
21
|
+
* pair. Pass `cwd` here whenever the session's cwd may have moved since construction.
|
|
22
|
+
* - **Aliases resolve but are not listed** (fix round 2, Medium A). `/.winter:review` resolves to
|
|
23
|
+
* the same skill `/review` does; only `review` is advertised. So the invariant is one-directional:
|
|
24
|
+
* everything listed resolves, but not everything that resolves is listed.
|
|
25
|
+
*
|
|
26
|
+
* WHAT ENFORCES IT: `FilesystemCommandResolver.enumerate()` is the single ordered map both `list()`
|
|
27
|
+
* and `resolve()` read. It used to be a claim resting on two loops happening to agree, and they did
|
|
28
|
+
* not -- `list()` walked command files first while `resolve()` walked skills first, so a shadowed
|
|
29
|
+
* name was listed with the LOSING producer's description and source, and an `off` skill put a name
|
|
30
|
+
* into `system/init.slash_commands` that `resolve()` answered `none` to.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildSlashCommandListing(resolver?: FilesystemCommandResolver, cwd?: string): SlashCommandInfo[];
|
|
33
|
+
/**
|
|
34
|
+
* `system/init.slash_commands` (`4874`): names only, in listing order.
|
|
35
|
+
*
|
|
36
|
+
* PASS `cwd` when the session's working directory may have moved since the resolver was built -- see
|
|
37
|
+
* the invariant above. Omitting it lists the construction cwd's namespace, which is correct at
|
|
38
|
+
* startup (when the init frame is emitted) and stale afterwards.
|
|
39
|
+
*/
|
|
40
|
+
export declare function slashCommandNames(resolver?: FilesystemCommandResolver, cwd?: string): string[];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { BrandProfile, SettingSource } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import { type SkillOverrides } from "../skills/listing.js";
|
|
3
|
+
import type { SkillIndex } from "../skills/store.js";
|
|
4
|
+
import { type CommandResolution, type CommandResolver } from "./seam.js";
|
|
5
|
+
/**
|
|
6
|
+
* Where a `/name` came from. `"builtin"` is the ENGINE's own (commands/seam.ts), never this
|
|
7
|
+
* resolver's; `"skill"` covers every skill tier, since the skill index has already ranked those.
|
|
8
|
+
*/
|
|
9
|
+
export type SlashCommandOrigin = "builtin" | "project" | "user" | "plugin" | "skill";
|
|
10
|
+
export interface SlashCommandInfo {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
/** `SlashCommand.argumentHint` (`sdk.d.ts:7932-7949`). */
|
|
14
|
+
argumentHint?: string;
|
|
15
|
+
source: SlashCommandOrigin;
|
|
16
|
+
}
|
|
17
|
+
/** One plugin's commands, pre-resolved by plugins/loader.ts. `name` is the BARE name; qualification happens here. */
|
|
18
|
+
export interface PluginCommandContribution {
|
|
19
|
+
plugin: string;
|
|
20
|
+
commands: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
path: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
argumentHint?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
export interface FilesystemCommandResolverOptions {
|
|
28
|
+
cwd: string;
|
|
29
|
+
/** The RESOLVED winter root (`<PREFIX>HOME` when set) -- see `SkillIndexOptions.winterHome` for why this is not called `home`. */
|
|
30
|
+
winterHome: string;
|
|
31
|
+
/** P7a (D19): the session's brand -- the project dot-dir the project tier walks. Omitted = `WINTER_BRAND`. */
|
|
32
|
+
brand?: Pick<BrandProfile, "projectDirName"> | undefined;
|
|
33
|
+
settingSources?: SettingSource[] | undefined;
|
|
34
|
+
/** The session's skill index. Skills create `/name` too (WS-11 §2.4) and WIN an overlap. */
|
|
35
|
+
skills?: SkillIndex | undefined;
|
|
36
|
+
plugins?: readonly PluginCommandContribution[] | undefined;
|
|
37
|
+
skillOverrides?: SkillOverrides | undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `zE`, ported. `namedArgs` is `o` (see this section's header -- always `[]` from every call site in
|
|
41
|
+
* this codebase today; no Winter frontmatter parser declares one yet).
|
|
42
|
+
*/
|
|
43
|
+
export declare function substituteArguments(body: string, args: string, namedArgs?: readonly string[]): string;
|
|
44
|
+
/**
|
|
45
|
+
* The workflow-invoke-line substitution ONLY (fix round 7). `workflows/store.ts`'s
|
|
46
|
+
* `buildWorkflowSkillPrompt` writes a static body whose invoke line embeds the raw args value INSIDE
|
|
47
|
+
* its own hand-written quotes (`args: $ARGUMENTS_JSON`), and that value needs `"`/`\` escaping the
|
|
48
|
+
* way claude's own `S(e)` does it -- dump-confirmed at `createWorkflowCommand`'s `getPromptForCommand`,
|
|
49
|
+
* `a=e?\`{ name: ${i}, args: ${S(e)} }\`:...\`, and controller-confirmed `S` is `JSON.stringify`
|
|
50
|
+
* (chunk export at dump ~269598). This function is DELIBERATELY SEPARATE from `substituteArguments`
|
|
51
|
+
* (never merged into it again): only a synthetic, workflow-backed skill body should ever have
|
|
52
|
+
* `$ARGUMENTS_JSON` recognised as a token at all; every other command/skill body must see claude's
|
|
53
|
+
* plain single-token behaviour, `$ARGUMENTS_JSON` included -- since claude itself would leave that
|
|
54
|
+
* text's `_JSON` suffix untouched.
|
|
55
|
+
*
|
|
56
|
+
* A single left-to-right scan, not two `.split().join()` passes: `JSON.stringify(args)` can itself
|
|
57
|
+
* contain the literal substring `$ARGUMENTS` (e.g. `args = "please pass $ARGUMENTS through"` stringifies
|
|
58
|
+
* to `"please pass $ARGUMENTS through"`), and a later, separate `$ARGUMENTS` pass over that already-
|
|
59
|
+
* substituted text would incorrectly re-substitute what the JSON pass just inserted. Scanning once,
|
|
60
|
+
* left to right, and advancing past whatever was just written never re-visits inserted text.
|
|
61
|
+
*/
|
|
62
|
+
export declare function substituteWorkflowArguments(body: string, args: string): string;
|
|
63
|
+
export declare class FilesystemCommandResolver implements CommandResolver {
|
|
64
|
+
private readonly opts;
|
|
65
|
+
/**
|
|
66
|
+
* The enumeration, memoized per `cwd`. `resolve()` receives a cwd (the spine's own signature) and a
|
|
67
|
+
* session's cwd genuinely moves -- EnterWorktree relocates the session root -- so a set fixed at
|
|
68
|
+
* construction would go stale for COMMAND FILES. SKILLS deliberately do NOT follow the cwd: they
|
|
69
|
+
* come from the index built once at startup, which is the same set the model sees in its listing
|
|
70
|
+
* and through the Skill tool. `/review` and `Skill("review")` resolving to different files would be
|
|
71
|
+
* the split brain the overlap rule exists to prevent.
|
|
72
|
+
*/
|
|
73
|
+
private readonly byCwd;
|
|
74
|
+
private constructor();
|
|
75
|
+
static build(opts: FilesystemCommandResolverOptions): FilesystemCommandResolver;
|
|
76
|
+
private scanCommandFiles;
|
|
77
|
+
/**
|
|
78
|
+
* THE single ordered enumeration. Insertion order IS precedence: skills first (the overlap rule),
|
|
79
|
+
* then command files (project nearest-first > user > plugin), first occurrence of a name winning.
|
|
80
|
+
*
|
|
81
|
+
* WHY ONE FUNCTION AND NOT TWO LOOPS. `list()` and `resolve()` used to walk opposite orders. For a
|
|
82
|
+
* name held by both a skill and a command file, `resolve()` returned the skill's body while the
|
|
83
|
+
* listing reported the command FILE's description, argument hint and source -- and an `off` skill
|
|
84
|
+
* put a name into `system/init.slash_commands` that `resolve()` answered `none` to, advertising a
|
|
85
|
+
* command nothing could run. Two orders over one namespace cannot be kept in agreement by care;
|
|
86
|
+
* they have to be one enumeration.
|
|
87
|
+
*/
|
|
88
|
+
private enumerate;
|
|
89
|
+
/**
|
|
90
|
+
* Every `/name` this resolver ADVERTISES, in enumeration order. Feeds `system/init.slash_commands`.
|
|
91
|
+
*
|
|
92
|
+
* PER CWD (fix round 2, Minor B): command files are discovered by a parent-walk from the cwd, so
|
|
93
|
+
* the answer differs between cwds and `cwd` defaults to the CONSTRUCTION cwd, not the live one.
|
|
94
|
+
* A caller must feed the SAME cwd to `list()` and `resolve()` for the "everything listed resolves"
|
|
95
|
+
* invariant to hold -- `slashCommandNames(resolver, cwd)` exists for exactly that.
|
|
96
|
+
*
|
|
97
|
+
* ALIASES ARE NOT LISTED (Medium A): `/.winter:review` resolves, but `slash_commands` carries
|
|
98
|
+
* `review` alone. Advertising both would double every project skill in the init frame and imply two
|
|
99
|
+
* commands where there is one.
|
|
100
|
+
*/
|
|
101
|
+
list(cwd?: string): SlashCommandInfo[];
|
|
102
|
+
resolve(prompt: string, cwd: string): Promise<CommandResolution>;
|
|
103
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `{ kind: "builtin" }` -- an engine-owned command. The union is deliberately a SINGLE literal today
|
|
3
|
+
* (`"compact"`): R5-14 ships `/compact [instructions]` now and marks every other built-in
|
|
4
|
+
* capture-pending, so a wider union would be inventing names the pinned surface has not been
|
|
5
|
+
* observed to have. Adding one later is a one-line widening plus an engine branch; a lane never
|
|
6
|
+
* produces this arm.
|
|
7
|
+
*
|
|
8
|
+
* `{ kind: "expand" }` -- `text` is the FULLY EXPANDED prompt (body with `$ARGUMENTS` already
|
|
9
|
+
* substituted); the engine substitutes nothing itself. `source` is a human-readable provenance
|
|
10
|
+
* string for diagnostics (e.g. a file path or `plugin:<name>`), never parsed.
|
|
11
|
+
*
|
|
12
|
+
* `{ kind: "none" }` -- not a command; the prompt is used verbatim.
|
|
13
|
+
*/
|
|
14
|
+
export type CommandResolution = {
|
|
15
|
+
kind: "builtin";
|
|
16
|
+
name: "compact";
|
|
17
|
+
args: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "expand";
|
|
20
|
+
text: string;
|
|
21
|
+
source: string;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "none";
|
|
24
|
+
};
|
|
25
|
+
export interface CommandResolver {
|
|
26
|
+
resolve(prompt: string, cwd: string): Promise<CommandResolution>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The one built-in, recognised by the engine before any resolver is consulted.
|
|
30
|
+
*
|
|
31
|
+
* Returns `undefined` for anything that is not a built-in -- including a bare `/` and any other
|
|
32
|
+
* `/name`, both of which fall through to the resolver.
|
|
33
|
+
*
|
|
34
|
+
* Grammar, deliberately narrow: `/compact` optionally followed by whitespace and free-form
|
|
35
|
+
* instructions, which are passed through verbatim (trimmed) as `custom_instructions`. `/compaction`
|
|
36
|
+
* is NOT a match -- the name must be the whole first token.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveBuiltinCommand(prompt: string): Extract<CommandResolution, {
|
|
39
|
+
kind: "builtin";
|
|
40
|
+
}> | undefined;
|
|
41
|
+
/** True for anything the engine should offer to a resolver at all -- see this file's header. */
|
|
42
|
+
export declare function looksLikeCommand(prompt: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The spine's test double: a resolver over a literal map of `name -> body`. `$ARGUMENTS` is
|
|
45
|
+
* substituted exactly as R5-14 requires so an engine test proves the engine passes the EXPANDED text
|
|
46
|
+
* on, and a lane has a producer to develop against.
|
|
47
|
+
*/
|
|
48
|
+
export declare function fakeCommandResolver(commands: Record<string, string>, opts?: {
|
|
49
|
+
calls?: Array<{
|
|
50
|
+
prompt: string;
|
|
51
|
+
cwd: string;
|
|
52
|
+
}>;
|
|
53
|
+
}): CommandResolver;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DEFAULT_COMPACTION_THRESHOLD } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import type { CompactionController } from "./seam.js";
|
|
3
|
+
export { DEFAULT_COMPACTION_THRESHOLD };
|
|
4
|
+
export interface CompactionControllerOptions {
|
|
5
|
+
/**
|
|
6
|
+
* R5-4's threshold, a DISCLOSED Winter session option (`RuntimeConfig.compactionThreshold`,
|
|
7
|
+
* default 0.92 -- the constant is the SDK's, declared once in options.ts). A value outside
|
|
8
|
+
* `(0, 1]` is ignored and the default stands, mirroring `createContextAccountant`'s own treatment
|
|
9
|
+
* of a nonsense limit: a threshold of 0 would compact before every single provider call and a
|
|
10
|
+
* threshold above 1 could never fire, and neither is a state a session should be able to reach by
|
|
11
|
+
* typo.
|
|
12
|
+
*/
|
|
13
|
+
compactionThreshold?: number;
|
|
14
|
+
/** How many user/assistant pairs survive a boundary. Default 4 (DEFAULT_RETAINED_PAIRS). */
|
|
15
|
+
retainedPairs?: number;
|
|
16
|
+
/** Overrides Winter's authored summary instruction. For fixtures and for a host with its own house style. */
|
|
17
|
+
instruction?: string;
|
|
18
|
+
/** Bounds the per-`tool_use` input rendering in the summarizer's view of the transcript. */
|
|
19
|
+
toolInputPreviewChars?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class NothingToCompactError extends Error {
|
|
22
|
+
}
|
|
23
|
+
export declare function createCompactionController(opts?: CompactionControllerOptions): CompactionController;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProviderMessage } from "../engine.js";
|
|
2
|
+
/** R5-4's own default: the last four user/assistant pairs. An option on the controller. */
|
|
3
|
+
export declare const DEFAULT_RETAINED_PAIRS = 4;
|
|
4
|
+
export interface RetentionPlan {
|
|
5
|
+
/**
|
|
6
|
+
* False when the window covers the whole history -- there is no cut that both keeps the requested
|
|
7
|
+
* pairs and folds anything. `retained` then holds the input unchanged and `summarized` is empty;
|
|
8
|
+
* the CONTROLLER turns this into a thrown error, because a `CompactionResult` whose `retained` is
|
|
9
|
+
* the whole input would make the engine's history LONGER (summary + everything) on every round.
|
|
10
|
+
*/
|
|
11
|
+
foldable: boolean;
|
|
12
|
+
/** The messages that survive the boundary, in order. */
|
|
13
|
+
retained: ProviderMessage[];
|
|
14
|
+
/** The messages the summary replaces -- what the summarizer is asked to condense. */
|
|
15
|
+
summarized: ProviderMessage[];
|
|
16
|
+
}
|
|
17
|
+
export interface RetentionOptions {
|
|
18
|
+
/** How many pairs (turns) to keep. Defaults to DEFAULT_RETAINED_PAIRS. */
|
|
19
|
+
pairs?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function selectRetention(messages: readonly ProviderMessage[], opts?: RetentionOptions): RetentionPlan;
|
|
22
|
+
/**
|
|
23
|
+
* WS-09 §8.5: the tools the compacted context still carries EVIDENCE of. `registry.onCompaction`
|
|
24
|
+
* resets the session's deferred loaded set to `evidenced ∩ still-registered`, so a tool whose call
|
|
25
|
+
* the summary swallowed goes back to searchable-not-loaded and must be rediscovered.
|
|
26
|
+
*
|
|
27
|
+
* DISCLOSED READING of the brief's "deferred tools referenced in retained messages": this returns
|
|
28
|
+
* EVERY referenced name, not a `descriptor.deferred`-filtered subset. The filtered set would be
|
|
29
|
+
* behaviourally identical at best -- `LoadedToolSet` only ever holds names Tool Search actually
|
|
30
|
+
* loaded, and `onCompaction` intersects rather than unions -- and strictly worse at worst: a
|
|
31
|
+
* descriptor whose `deferred` is a `PermissionMode[]` reads as not-deferred outside those modes, so
|
|
32
|
+
* filtering here would silently unload a tool the model is still visibly using. Over-reporting
|
|
33
|
+
* cannot add anything to the loaded set; under-reporting drops something from it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function evidencedToolNames(retained: readonly ProviderMessage[]): string[];
|