@wrongstack/core 0.1.4 → 0.1.8

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 ADDED
@@ -0,0 +1,155 @@
1
+ # @wrongstack/core
2
+
3
+ Kernel, types, and default implementations that drive the WrongStack CLI agent.
4
+
5
+ This package has no `bin`. It's a library you'd depend on if you were building a plugin, embedding the agent in another tool, or replacing one of the default implementations (a custom session store, a stricter permission policy, your own retry strategy).
6
+
7
+ If you're just using WrongStack from the terminal, install [`wrongstack`](../../README.md) instead.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pnpm add @wrongstack/core
13
+ ```
14
+
15
+ Requires **Node.js ≥ 22.0.0**.
16
+
17
+ ## What's in here
18
+
19
+ ```
20
+ src/
21
+ core/ — Agent, Context, ConversationState, ProviderRunner, InputBuilder
22
+ defaults/ — Production-ready implementations (session store, secret vault, …)
23
+ kernel/ — Container, TOKENS, EventBus, ToolRegistry, ProviderRegistry
24
+ plugin/ — Plugin loader, PluginAPI, manifest validation
25
+ registry/ — SlashCommandRegistry, ToolRegistry, ProviderRegistry
26
+ types/ — Public type surface (Tool, Provider, SessionStore, …)
27
+ utils/ — wstack-paths, safe-json, deterministic-stringify, lru-cache
28
+ ```
29
+
30
+ ## Quick example
31
+
32
+ Run an agent loop with the Anthropic provider and a single tool:
33
+
34
+ ```ts
35
+ import {
36
+ Agent,
37
+ Container,
38
+ Context,
39
+ DefaultEventBus,
40
+ DefaultLogger,
41
+ DefaultPermissionPolicy,
42
+ DefaultSessionStore,
43
+ DefaultSystemPromptBuilder,
44
+ DefaultTokenCounter,
45
+ ToolRegistry,
46
+ TOKENS,
47
+ } from '@wrongstack/core';
48
+ import { AnthropicProvider } from '@wrongstack/providers';
49
+ import { readTool, writeTool, bashTool } from '@wrongstack/tools';
50
+
51
+ const container = new Container();
52
+ container.bind(TOKENS.EventBus, () => new DefaultEventBus());
53
+ container.bind(TOKENS.Logger, () => new DefaultLogger());
54
+ container.bind(TOKENS.PermissionPolicy, () => new DefaultPermissionPolicy());
55
+
56
+ const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! });
57
+ const tools = new ToolRegistry([readTool, writeTool, bashTool]);
58
+
59
+ const ctx = new Context({
60
+ cwd: process.cwd(),
61
+ projectRoot: process.cwd(),
62
+ provider,
63
+ model: 'claude-sonnet-4-6',
64
+ tokenCounter: new DefaultTokenCounter({ providerId: 'anthropic' }),
65
+ });
66
+
67
+ const agent = new Agent({
68
+ container,
69
+ ctx,
70
+ tools,
71
+ systemPromptBuilder: new DefaultSystemPromptBuilder(),
72
+ });
73
+
74
+ const result = await agent.run({
75
+ input: { text: 'list the files in src/' },
76
+ });
77
+
78
+ console.log(result.assistantText);
79
+ ```
80
+
81
+ ## Replacing a default
82
+
83
+ Every concrete class under `defaults/` implements an interface in `types/`. The container resolves by token, so swapping is a one-line change:
84
+
85
+ ```ts
86
+ import { TOKENS } from '@wrongstack/core';
87
+
88
+ class StrictPolicy implements PermissionPolicy {
89
+ async check(tool, input, ctx) {
90
+ if (tool.name === 'bash') return { decision: 'deny', reason: 'no shell' };
91
+ return { decision: 'allow' };
92
+ }
93
+ }
94
+
95
+ container.bind(TOKENS.PermissionPolicy, () => new StrictPolicy());
96
+ ```
97
+
98
+ The same pattern works for `SessionStore`, `MemoryStore`, `SystemPromptBuilder`, `RetryPolicy`, `ErrorHandler`, `TokenCounter`, `SecretVault`, `SecretScrubber`, `Compactor`, `ConfigStore`, `ModelsRegistry`, `ModeStore`.
99
+
100
+ ## Building a tool
101
+
102
+ ```ts
103
+ import type { Tool } from '@wrongstack/core';
104
+
105
+ export const echoTool: Tool<{ text: string }, string> = {
106
+ name: 'echo',
107
+ description: 'Echo a string back.',
108
+ inputSchema: {
109
+ type: 'object',
110
+ properties: { text: { type: 'string' } },
111
+ required: ['text'],
112
+ },
113
+ permission: 'auto',
114
+ mutating: false,
115
+ async execute(input) {
116
+ return input.text;
117
+ },
118
+ };
119
+ ```
120
+
121
+ See [docs/tool-author-guide.md](../../docs/tool-author-guide.md) for the full contract (`subjectKey`, `executeStream`, `cleanup`, abort handling, output bounds).
122
+
123
+ ## Building a provider
124
+
125
+ Most providers can ride the declarative wire-format adapter — see [`@wrongstack/providers`](../providers). For direct implementation, see [docs/provider-author-guide.md](../../docs/provider-author-guide.md).
126
+
127
+ ## Building a plugin
128
+
129
+ ```ts
130
+ import type { Plugin } from '@wrongstack/core';
131
+
132
+ export default {
133
+ name: 'my-plugin',
134
+ version: '1.0.0',
135
+ capabilities: { tools: true, slashCommands: true },
136
+ async setup(api) {
137
+ api.registerTool(myTool);
138
+ api.registerSlashCommand({ name: 'my-cmd', description: '…', run: async () => {} });
139
+ },
140
+ } satisfies Plugin;
141
+ ```
142
+
143
+ See [docs/plugin-author-guide.md](../../docs/plugin-author-guide.md).
144
+
145
+ ## Path layout
146
+
147
+ All developer-level state lives under `~/.wrongstack/`. Per-project state is keyed by `sha256(absoluteProjectRoot).slice(0,12)` under `~/.wrongstack/projects/<hash>/`. The only thing inside the project tree itself is the optional, committable `.wrongstack/AGENTS.md` and `.wrongstack/skills/`. See `WstackPaths` in [utils/wstack-paths.ts](src/utils/wstack-paths.ts) for the full layout.
148
+
149
+ ## Security model
150
+
151
+ See [SECURITY.md](../../SECURITY.md) at the repo root for the threat model, adversary trust assumptions, and the catalog of controls (SSRF defenses, child-env sanitization, secret vault, prompt-injection assumptions for LLM-generated tool inputs).
152
+
153
+ ## License
154
+
155
+ MIT