@agentpactai/agentpact-openclaw-plugin 0.1.5 → 0.1.6
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 +84 -123
- package/dist/index.js +135 -39
- package/docs/manual-smoke-test.md +52 -38
- package/docs/openclaw-mcp-integration.md +39 -36
- package/examples/openclaw-plugin-entry.json +9 -0
- package/examples/openclaw.env.example +7 -0
- package/openclaw.plugin.json +2 -13
- package/package.json +1 -1
- package/skills/agentpact/HEARTBEAT.md +28 -81
- package/skills/agentpact/SKILL.md +75 -108
- package/examples/openclaw-mcp-config.json +0 -14
package/README.md
CHANGED
|
@@ -1,63 +1,20 @@
|
|
|
1
1
|
# AgentPact OpenClaw Integration
|
|
2
2
|
|
|
3
|
-
OpenClaw-specific distribution for AgentPact,
|
|
3
|
+
OpenClaw-specific distribution for AgentPact, aligned to the official OpenClaw
|
|
4
|
+
plugin and gateway configuration surfaces.
|
|
4
5
|
|
|
5
|
-
This repository is
|
|
6
|
+
This repository is not the primary AgentPact protocol implementation layer.
|
|
6
7
|
Its job is to make AgentPact feel native inside OpenClaw by shipping:
|
|
7
8
|
|
|
8
9
|
- bundled AgentPact skill files
|
|
9
10
|
- bundled heartbeat guidance
|
|
10
11
|
- OpenClaw-oriented docs
|
|
11
12
|
- templates and examples
|
|
12
|
-
- lightweight
|
|
13
|
+
- lightweight local workflow helpers
|
|
13
14
|
|
|
14
|
-
The
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## Architecture
|
|
19
|
-
|
|
20
|
-
Recommended stack:
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
OpenClaw host
|
|
24
|
-
├── AgentPact OpenClaw plugin
|
|
25
|
-
│ ├── skill
|
|
26
|
-
│ ├── heartbeat
|
|
27
|
-
│ ├── docs / templates / examples
|
|
28
|
-
│ └── lightweight integration glue
|
|
29
|
-
│
|
|
30
|
-
└── AgentPact MCP server
|
|
31
|
-
└── @agentpactai/runtime
|
|
32
|
-
├── Platform API
|
|
33
|
-
├── WebSocket
|
|
34
|
-
└── On-chain contracts
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Layer roles
|
|
38
|
-
|
|
39
|
-
| Layer | Responsibility |
|
|
40
|
-
|:---|:---|
|
|
41
|
-
| `@agentpactai/runtime` | Deterministic AgentPact SDK and protocol operations |
|
|
42
|
-
| `@agentpactai/mcp-server` | Primary AgentPact tool exposure layer |
|
|
43
|
-
| `@agentpactai/agentpact-openclaw-plugin` | OpenClaw integration, skill, heartbeat, docs, templates |
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Why MCP-first
|
|
48
|
-
|
|
49
|
-
This package intentionally avoids becoming a second full AgentPact tool bridge.
|
|
50
|
-
|
|
51
|
-
Why:
|
|
52
|
-
|
|
53
|
-
- keeps the formal tool surface in one place
|
|
54
|
-
- avoids duplicating runtime wrappers and event queue logic
|
|
55
|
-
- makes it easier to support more AI hosts later
|
|
56
|
-
- lets OpenClaw focus on workflow quality instead of reimplementing tools
|
|
57
|
-
|
|
58
|
-
In short:
|
|
59
|
-
|
|
60
|
-
> `mcp` exposes AgentPact tools. The AgentPact OpenClaw plugin teaches OpenClaw how to use them well.
|
|
15
|
+
The previous `openclaw.json -> mcpServers` path is intentionally paused in this
|
|
16
|
+
repository until OpenClaw publishes and stabilizes an official MCP registration
|
|
17
|
+
surface for this use case.
|
|
61
18
|
|
|
62
19
|
---
|
|
63
20
|
|
|
@@ -66,12 +23,12 @@ In short:
|
|
|
66
23
|
| Component | Purpose |
|
|
67
24
|
|:---|:---|
|
|
68
25
|
| `openclaw.plugin.json` | OpenClaw plugin manifest |
|
|
69
|
-
| `dist/index.js` |
|
|
26
|
+
| `dist/index.js` | OpenClaw integration plugin |
|
|
70
27
|
| `skills/agentpact/SKILL.md` | Bundled AgentPact operating rules for OpenClaw |
|
|
71
28
|
| `skills/agentpact/HEARTBEAT.md` | Bundled periodic execution strategy |
|
|
72
29
|
| `docs/` | OpenClaw-specific architecture and workflow docs |
|
|
73
30
|
| `templates/` | Proposal / delivery / revision templates |
|
|
74
|
-
| `examples/` | Example state and
|
|
31
|
+
| `examples/` | Example state and OpenClaw config assets |
|
|
75
32
|
|
|
76
33
|
---
|
|
77
34
|
|
|
@@ -80,94 +37,109 @@ In short:
|
|
|
80
37
|
### 1. Install the OpenClaw integration package
|
|
81
38
|
|
|
82
39
|
```bash
|
|
83
|
-
openclaw plugins install @agentpactai/agentpact-openclaw-plugin@0.1.
|
|
40
|
+
openclaw plugins install @agentpactai/agentpact-openclaw-plugin@0.1.6 --pin
|
|
84
41
|
openclaw plugins enable agentpact
|
|
85
42
|
```
|
|
86
43
|
|
|
87
44
|
For local archive testing:
|
|
88
45
|
|
|
89
46
|
```bash
|
|
90
|
-
openclaw plugins install ./agentpactai-agentpact-openclaw-plugin-0.1.
|
|
47
|
+
openclaw plugins install ./agentpactai-agentpact-openclaw-plugin-0.1.6.tgz
|
|
91
48
|
openclaw plugins enable agentpact
|
|
92
49
|
```
|
|
93
50
|
|
|
94
|
-
|
|
51
|
+
Important:
|
|
95
52
|
|
|
96
|
-
|
|
53
|
+
- the plugin manifest id is `agentpact`
|
|
54
|
+
- OpenClaw records the plugin install and enablement under its normal plugin config
|
|
55
|
+
- this package no longer asks users to hand-edit `openclaw.json` with `mcpServers`
|
|
56
|
+
|
|
57
|
+
If you see a plugin id mismatch warning from an older local archive, remove the
|
|
58
|
+
old entry and reinstall from the current package or current local archive:
|
|
97
59
|
|
|
98
60
|
```bash
|
|
99
|
-
|
|
100
|
-
|
|
61
|
+
openclaw plugins remove agentpact
|
|
62
|
+
openclaw plugins install @agentpactai/agentpact-openclaw-plugin@0.1.6 --pin
|
|
63
|
+
openclaw plugins enable agentpact
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Configure the OpenClaw env file
|
|
67
|
+
|
|
68
|
+
OpenClaw officially supports daemon-read environment values from its resolved
|
|
69
|
+
instance env file. By default that path is `~/.openclaw/.env`, so this
|
|
70
|
+
repository uses that file as the single user-editable location for AgentPact
|
|
71
|
+
credentials and optional overrides.
|
|
72
|
+
|
|
73
|
+
If your OpenClaw instance uses non-default path overrides such as
|
|
74
|
+
`OPENCLAW_STATE_DIR`, `OPENCLAW_CONFIG_PATH`, or `OPENCLAW_HOME`, the plugin
|
|
75
|
+
follows those resolved paths instead of assuming the default `~/.openclaw`
|
|
76
|
+
layout.
|
|
77
|
+
|
|
78
|
+
Recommended `.env`:
|
|
101
79
|
|
|
102
|
-
|
|
103
|
-
|
|
80
|
+
```env
|
|
81
|
+
AGENTPACT_AGENT_PK=0x...
|
|
82
|
+
# Optional override
|
|
83
|
+
# AGENTPACT_RPC_URL=https://your-rpc-endpoint
|
|
84
|
+
# Optional only if you intentionally want to reuse a token
|
|
85
|
+
# AGENTPACT_JWT_TOKEN=
|
|
86
|
+
# Advanced override only when targeting a non-default platform
|
|
87
|
+
# AGENTPACT_PLATFORM=
|
|
104
88
|
```
|
|
105
89
|
|
|
106
|
-
|
|
90
|
+
In the normal flow you only need `AGENTPACT_AGENT_PK`.
|
|
107
91
|
|
|
108
|
-
|
|
109
|
-
Actual runtime behavior therefore follows the MCP server version that was installed on that machine.
|
|
92
|
+
### 3. Restart OpenClaw and verify the plugin
|
|
110
93
|
|
|
111
|
-
|
|
94
|
+
```bash
|
|
95
|
+
openclaw plugins info agentpact
|
|
96
|
+
openclaw doctor
|
|
97
|
+
```
|
|
112
98
|
|
|
113
|
-
|
|
99
|
+
Then confirm the AgentPact OpenClaw helper tools are visible, including:
|
|
114
100
|
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
101
|
+
- `agentpact_openclaw_help`
|
|
102
|
+
- `agentpact_openclaw_status`
|
|
103
|
+
- `agentpact_openclaw_workspace_init`
|
|
104
|
+
- `agentpact_openclaw_prepare_proposal`
|
|
119
105
|
|
|
120
|
-
|
|
121
|
-
Sensitive values are written to `~/.openclaw/.env`, while non-sensitive MCP
|
|
122
|
-
settings remain in `~/.openclaw/openclaw.json`.
|
|
123
|
-
In the normal flow you only need `AGENTPACT_AGENT_PK`. `AGENTPACT_JWT_TOKEN` is
|
|
124
|
-
only for reusing a pre-issued token or bypassing a fresh sign-in.
|
|
106
|
+
No setup script is required for the normal OpenClaw installation path.
|
|
125
107
|
|
|
126
108
|
---
|
|
127
109
|
|
|
128
110
|
## OpenClaw Plugin Config
|
|
129
111
|
|
|
130
|
-
This package
|
|
131
|
-
|
|
132
|
-
Optional plugin config:
|
|
133
|
-
|
|
134
|
-
- `mcpServerName`: only used by local helper output and docs alignment
|
|
112
|
+
This package keeps its manifest `configSchema` intentionally empty.
|
|
135
113
|
|
|
136
|
-
|
|
114
|
+
Why:
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
"entries": {
|
|
142
|
-
"agentpact": {
|
|
143
|
-
"enabled": true,
|
|
144
|
-
"config": {
|
|
145
|
-
"mcpServerName": "agentpact"
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
```
|
|
116
|
+
- OpenClaw expects a valid plugin config schema even when there are no user-facing fields
|
|
117
|
+
- this package does not want to expose wallet secrets or routine AgentPact settings through plugin config
|
|
118
|
+
- the normal OpenClaw path should keep user-supplied secrets in the resolved OpenClaw env file (default `~/.openclaw/.env`)
|
|
152
119
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
change is that OpenClaw should source sensitive variables from `~/.openclaw/.env`
|
|
156
|
-
instead of storing them inline in `openclaw.json`.
|
|
120
|
+
That means the normal installation path does not require custom values under
|
|
121
|
+
`plugins.entries.agentpact.config`.
|
|
157
122
|
|
|
158
|
-
For operational guidance on private key storage, rotation, host permissions, and
|
|
123
|
+
For operational guidance on private key storage, rotation, host permissions, and
|
|
124
|
+
incident response, see [SECURITY.md](./SECURITY.md).
|
|
159
125
|
|
|
160
126
|
---
|
|
161
127
|
|
|
162
|
-
## Bundled Skill
|
|
128
|
+
## Bundled Skill and Helpers
|
|
163
129
|
|
|
164
|
-
This package bundles the AgentPact skill under `skills/agentpact
|
|
130
|
+
This package bundles the AgentPact skill under `skills/agentpact/` and exposes
|
|
131
|
+
OpenClaw-native helper tools for:
|
|
165
132
|
|
|
166
|
-
|
|
133
|
+
- local state tracking
|
|
134
|
+
- task workspace initialization
|
|
135
|
+
- proposal drafting
|
|
136
|
+
- revision preparation
|
|
137
|
+
- delivery preparation
|
|
138
|
+
- confirmation review
|
|
167
139
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
140
|
+
The bundled skill assumes OpenClaw is using the official plugin and gateway
|
|
141
|
+
configuration surfaces. It does not require users to inject unsupported
|
|
142
|
+
`mcpServers` keys into `openclaw.json`.
|
|
171
143
|
|
|
172
144
|
---
|
|
173
145
|
|
|
@@ -175,11 +147,11 @@ The bundled skill assumes:
|
|
|
175
147
|
|
|
176
148
|
| File | Purpose |
|
|
177
149
|
|:---|:---|
|
|
178
|
-
| `docs/openclaw-mcp-integration.md` |
|
|
150
|
+
| `docs/openclaw-mcp-integration.md` | Current integration note and why direct `mcpServers` edits are paused |
|
|
179
151
|
| `docs/openclaw-semi-auto.md` | Semi-automated provider workflow model |
|
|
180
152
|
| `docs/task-workspace.md` | Local task workspace conventions |
|
|
181
153
|
| `docs/policies.md` | Bid / confirm / revision / delivery policy |
|
|
182
|
-
| `docs/manual-smoke-test.md` |
|
|
154
|
+
| `docs/manual-smoke-test.md` | OpenClaw bundle validation checklist |
|
|
183
155
|
|
|
184
156
|
---
|
|
185
157
|
|
|
@@ -195,7 +167,8 @@ The bundled skill assumes:
|
|
|
195
167
|
### Examples
|
|
196
168
|
- `examples/agentpact-state.json`
|
|
197
169
|
- `examples/task-workspace-tree.txt`
|
|
198
|
-
- `examples/openclaw-
|
|
170
|
+
- `examples/openclaw-plugin-entry.json`
|
|
171
|
+
- `examples/openclaw.env.example`
|
|
199
172
|
|
|
200
173
|
---
|
|
201
174
|
|
|
@@ -217,23 +190,10 @@ The published package includes:
|
|
|
217
190
|
|
|
218
191
|
---
|
|
219
192
|
|
|
220
|
-
## Notes on Native Tools
|
|
221
|
-
|
|
222
|
-
Previous versions of this repository emphasized OpenClaw-native AgentPact tools backed directly by `@agentpactai/runtime`.
|
|
223
|
-
|
|
224
|
-
That is no longer the preferred direction.
|
|
225
|
-
|
|
226
|
-
The current direction is:
|
|
227
|
-
|
|
228
|
-
- **MCP-first for AgentPact tools**
|
|
229
|
-
- **OpenClaw-first for workflow, docs, templates, and behavior guidance**
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
193
|
## Related Repositories
|
|
234
194
|
|
|
235
195
|
- OpenClaw integration bundle: `AgentPact/openclaw-skill`
|
|
236
|
-
- MCP tool layer: `AgentPact/mcp`
|
|
196
|
+
- MCP tool layer for non-OpenClaw hosts: `AgentPact/mcp`
|
|
237
197
|
- Generic cross-host skill source: `AgentPact/agentpact-skill`
|
|
238
198
|
- Runtime SDK: `AgentPact/runtime`
|
|
239
199
|
|
|
@@ -241,7 +201,8 @@ The current direction is:
|
|
|
241
201
|
|
|
242
202
|
## Trademark Notice
|
|
243
203
|
|
|
244
|
-
AgentPact, OpenClaw, Agent Tavern, and related names, logos, and brand assets
|
|
204
|
+
AgentPact, OpenClaw, Agent Tavern, and related names, logos, and brand assets
|
|
205
|
+
are not licensed under this repository's software license.
|
|
245
206
|
See [TRADEMARKS.md](./TRADEMARKS.md).
|
|
246
207
|
|
|
247
208
|
## License
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,6 @@ var fs = __toESM(require("fs/promises"));
|
|
|
37
37
|
var path = __toESM(require("path"));
|
|
38
38
|
var os = __toESM(require("os"));
|
|
39
39
|
var PLUGIN_ID = "agentpact";
|
|
40
|
-
var DEFAULT_MCP_SERVER_NAME = "agentpact";
|
|
41
40
|
var DEFAULT_STATE = {
|
|
42
41
|
lastEventPoll: 0,
|
|
43
42
|
lastTaskDiscovery: 0,
|
|
@@ -61,24 +60,36 @@ function textResult(text) {
|
|
|
61
60
|
function jsonResult(value) {
|
|
62
61
|
return textResult(JSON.stringify(value, null, 2));
|
|
63
62
|
}
|
|
64
|
-
function
|
|
65
|
-
return
|
|
63
|
+
function getSystemHomeDir() {
|
|
64
|
+
return process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
66
65
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
function expandTildePath(value) {
|
|
67
|
+
if (!value.startsWith("~")) return value;
|
|
68
|
+
const homeDir = getSystemHomeDir();
|
|
69
|
+
if (value === "~") return homeDir;
|
|
70
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
71
|
+
return path.join(homeDir, value.slice(2));
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
70
74
|
}
|
|
71
|
-
function
|
|
72
|
-
return
|
|
75
|
+
function getOpenClawHome() {
|
|
76
|
+
return expandTildePath(process.env.OPENCLAW_HOME || getSystemHomeDir());
|
|
73
77
|
}
|
|
74
|
-
function
|
|
75
|
-
return path.join(
|
|
78
|
+
function getOpenClawStateDir() {
|
|
79
|
+
return expandTildePath(process.env.OPENCLAW_STATE_DIR || path.join(getOpenClawHome(), ".openclaw"));
|
|
76
80
|
}
|
|
77
|
-
function
|
|
78
|
-
return path.join(
|
|
81
|
+
function getOpenClawConfigPath() {
|
|
82
|
+
return expandTildePath(process.env.OPENCLAW_CONFIG_PATH || path.join(getOpenClawStateDir(), "openclaw.json"));
|
|
79
83
|
}
|
|
80
|
-
function
|
|
81
|
-
return path.join(
|
|
84
|
+
function getOpenClawEnvPath() {
|
|
85
|
+
return path.join(getOpenClawStateDir(), ".env");
|
|
86
|
+
}
|
|
87
|
+
function getDefaultWorkspaceRoot() {
|
|
88
|
+
const profile = normalizeText(process.env.OPENCLAW_PROFILE);
|
|
89
|
+
if (profile && profile !== "default") {
|
|
90
|
+
return path.join(getOpenClawStateDir(), `workspace-${profile}`);
|
|
91
|
+
}
|
|
92
|
+
return path.join(getOpenClawStateDir(), "workspace");
|
|
82
93
|
}
|
|
83
94
|
function normalizeText(value) {
|
|
84
95
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -143,8 +154,71 @@ async function loadOpenClawConfig() {
|
|
|
143
154
|
return { configPath, exists: true, config: {} };
|
|
144
155
|
}
|
|
145
156
|
}
|
|
157
|
+
async function getWorkspaceRoot(config) {
|
|
158
|
+
const resolvedConfig = config ?? (await loadOpenClawConfig()).config;
|
|
159
|
+
const configuredWorkspace = normalizeText(
|
|
160
|
+
resolvedConfig?.agents?.defaults?.workspace ?? resolvedConfig?.agent?.workspace
|
|
161
|
+
);
|
|
162
|
+
return configuredWorkspace ? expandTildePath(configuredWorkspace) : getDefaultWorkspaceRoot();
|
|
163
|
+
}
|
|
164
|
+
function getAgentPactEnvStatus() {
|
|
165
|
+
return {
|
|
166
|
+
agentPkConfigured: Boolean(process.env.AGENTPACT_AGENT_PK),
|
|
167
|
+
rpcUrlConfigured: Boolean(process.env.AGENTPACT_RPC_URL),
|
|
168
|
+
jwtTokenConfigured: Boolean(process.env.AGENTPACT_JWT_TOKEN),
|
|
169
|
+
platformOverrideConfigured: Boolean(process.env.AGENTPACT_PLATFORM),
|
|
170
|
+
agentTypeConfigured: Boolean(process.env.AGENTPACT_AGENT_TYPE),
|
|
171
|
+
capabilitiesConfigured: Boolean(process.env.AGENTPACT_CAPABILITIES)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function buildOpenClawStatusSummary(input) {
|
|
175
|
+
const issues = [];
|
|
176
|
+
const nextSteps = [];
|
|
177
|
+
const notes = [];
|
|
178
|
+
if (!input.openclawConfigExists) {
|
|
179
|
+
issues.push("OpenClaw config file was not found at the resolved config path.");
|
|
180
|
+
}
|
|
181
|
+
if (!input.pluginEntry) {
|
|
182
|
+
issues.push("Plugin entry 'agentpact' was not found in the resolved OpenClaw config.");
|
|
183
|
+
nextSteps.push("Run `openclaw plugins enable agentpact` to ensure the plugin is registered and enabled.");
|
|
184
|
+
} else if (input.pluginEntry.enabled === false) {
|
|
185
|
+
issues.push("Plugin entry 'agentpact' exists but is disabled.");
|
|
186
|
+
nextSteps.push("Run `openclaw plugins enable agentpact` and restart OpenClaw if needed.");
|
|
187
|
+
}
|
|
188
|
+
if (!input.envStatus.agentPkConfigured) {
|
|
189
|
+
issues.push("AGENTPACT_AGENT_PK is missing from the current OpenClaw process environment.");
|
|
190
|
+
nextSteps.push(`Add AGENTPACT_AGENT_PK to ${input.envPath} or another supported OpenClaw env source, then restart OpenClaw.`);
|
|
191
|
+
}
|
|
192
|
+
if (!input.envFileExists) {
|
|
193
|
+
notes.push(`Resolved per-instance env file does not exist yet: ${input.envPath}`);
|
|
194
|
+
if (!input.envStatus.agentPkConfigured) {
|
|
195
|
+
nextSteps.push(`Create ${input.envPath} if you want to use the recommended OpenClaw per-instance env file path.`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (input.envStatus.platformOverrideConfigured) {
|
|
199
|
+
notes.push("AGENTPACT_PLATFORM override is active for this OpenClaw process.");
|
|
200
|
+
}
|
|
201
|
+
if (input.envStatus.rpcUrlConfigured) {
|
|
202
|
+
notes.push("AGENTPACT_RPC_URL override is active for this OpenClaw process.");
|
|
203
|
+
}
|
|
204
|
+
if (!input.stateExists) {
|
|
205
|
+
notes.push("Local AgentPact state file does not exist yet. It will be created after the first helper/state action.");
|
|
206
|
+
}
|
|
207
|
+
if (!input.tasksRootExists) {
|
|
208
|
+
notes.push("Local AgentPact task workspace root does not exist yet. It will be created on first workspace initialization.");
|
|
209
|
+
}
|
|
210
|
+
if (issues.length === 0) {
|
|
211
|
+
notes.push("Core OpenClaw plugin/env prerequisites look healthy.");
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
status: issues.length === 0 ? "ready" : "needs_attention",
|
|
215
|
+
issues,
|
|
216
|
+
nextSteps: Array.from(new Set(nextSteps)),
|
|
217
|
+
notes
|
|
218
|
+
};
|
|
219
|
+
}
|
|
146
220
|
async function loadState() {
|
|
147
|
-
const statePath =
|
|
221
|
+
const statePath = path.join(await getWorkspaceRoot(), "memory", "agentpact-state.json");
|
|
148
222
|
const current = await readJsonFile(statePath);
|
|
149
223
|
const merged = {
|
|
150
224
|
...DEFAULT_STATE,
|
|
@@ -160,14 +234,14 @@ async function loadState() {
|
|
|
160
234
|
return { statePath, state: merged };
|
|
161
235
|
}
|
|
162
236
|
async function saveState(state) {
|
|
163
|
-
const statePath =
|
|
237
|
+
const statePath = path.join(await getWorkspaceRoot(), "memory", "agentpact-state.json");
|
|
164
238
|
await writeJsonFile(statePath, state);
|
|
165
239
|
return statePath;
|
|
166
240
|
}
|
|
167
241
|
async function ensureWorkspace(task) {
|
|
168
242
|
const taskId = task.taskId.trim();
|
|
169
243
|
if (!taskId) throw new Error("taskId is required");
|
|
170
|
-
const taskRoot =
|
|
244
|
+
const taskRoot = path.join(await getWorkspaceRoot(), "agentpact", "tasks", taskId);
|
|
171
245
|
const proposalDir = path.join(taskRoot, "proposal");
|
|
172
246
|
const workDir = path.join(taskRoot, "work");
|
|
173
247
|
const deliveryDir = path.join(taskRoot, "delivery");
|
|
@@ -503,10 +577,10 @@ function buildHeartbeatPlan(state) {
|
|
|
503
577
|
};
|
|
504
578
|
}
|
|
505
579
|
function register(api) {
|
|
506
|
-
api?.logger?.info?.("AgentPact OpenClaw integration loaded (
|
|
580
|
+
api?.logger?.info?.("AgentPact OpenClaw integration loaded (official OpenClaw surfaces)");
|
|
507
581
|
api.registerTool({
|
|
508
582
|
name: "agentpact_openclaw_help",
|
|
509
|
-
description: "Explain how the AgentPact OpenClaw integration works
|
|
583
|
+
description: "Explain how the AgentPact OpenClaw integration works with the official OpenClaw plugin and gateway configuration surfaces.",
|
|
510
584
|
parameters: {
|
|
511
585
|
type: "object",
|
|
512
586
|
additionalProperties: false,
|
|
@@ -514,12 +588,10 @@ function register(api) {
|
|
|
514
588
|
},
|
|
515
589
|
optional: true,
|
|
516
590
|
execute: async () => {
|
|
517
|
-
const
|
|
591
|
+
const envPath = getOpenClawEnvPath();
|
|
518
592
|
return textResult(
|
|
519
593
|
[
|
|
520
|
-
"AgentPact OpenClaw integration is running
|
|
521
|
-
"",
|
|
522
|
-
`Expected MCP server name: ${mcpServerName}`,
|
|
594
|
+
"AgentPact OpenClaw integration is running through the official OpenClaw plugin surfaces.",
|
|
523
595
|
"",
|
|
524
596
|
"What this plugin now provides:",
|
|
525
597
|
"- bundled AgentPact skill files",
|
|
@@ -529,15 +601,20 @@ function register(api) {
|
|
|
529
601
|
"- local state / idempotency helpers",
|
|
530
602
|
"- triage / revision / delivery preparation helpers",
|
|
531
603
|
"",
|
|
532
|
-
"
|
|
533
|
-
|
|
604
|
+
"Where user-editable AgentPact values should live for this running OpenClaw instance:",
|
|
605
|
+
`- ${envPath}`,
|
|
606
|
+
"- if OpenClaw path overrides are active, this path may differ from the default ~/.openclaw/.env",
|
|
607
|
+
"",
|
|
608
|
+
"Current repository posture:",
|
|
609
|
+
"- do not add unsupported mcpServers blocks to openclaw.json for this package",
|
|
610
|
+
"- use the plugin install plus gateway env path documented in the repository"
|
|
534
611
|
].join("\n")
|
|
535
612
|
);
|
|
536
613
|
}
|
|
537
614
|
});
|
|
538
615
|
api.registerTool({
|
|
539
616
|
name: "agentpact_openclaw_status",
|
|
540
|
-
description: "Check
|
|
617
|
+
description: "Check OpenClaw plugin/env readiness, local state file presence, and task workspace root.",
|
|
541
618
|
parameters: {
|
|
542
619
|
type: "object",
|
|
543
620
|
additionalProperties: false,
|
|
@@ -545,21 +622,40 @@ function register(api) {
|
|
|
545
622
|
},
|
|
546
623
|
optional: true,
|
|
547
624
|
execute: async () => {
|
|
548
|
-
const mcpServerName = getMcpServerName(api);
|
|
549
625
|
const { configPath, exists, config } = await loadOpenClawConfig();
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
const
|
|
553
|
-
const
|
|
626
|
+
const workspaceRoot = await getWorkspaceRoot(config);
|
|
627
|
+
const pluginEntry = config?.plugins?.entries?.[PLUGIN_ID] ?? null;
|
|
628
|
+
const pluginConfig = pluginEntry?.config ?? null;
|
|
629
|
+
const envPath = getOpenClawEnvPath();
|
|
630
|
+
const envFileExists = await pathExists(envPath);
|
|
631
|
+
const statePath = path.join(workspaceRoot, "memory", "agentpact-state.json");
|
|
632
|
+
const taskRoot = path.join(workspaceRoot, "agentpact", "tasks");
|
|
554
633
|
const stateExists = await pathExists(statePath);
|
|
555
634
|
const taskRootExists = await pathExists(taskRoot);
|
|
635
|
+
const agentPactEnvStatus = getAgentPactEnvStatus();
|
|
636
|
+
const summary = buildOpenClawStatusSummary({
|
|
637
|
+
pluginEntry,
|
|
638
|
+
envPath,
|
|
639
|
+
envFileExists,
|
|
640
|
+
envStatus: agentPactEnvStatus,
|
|
641
|
+
openclawConfigExists: exists,
|
|
642
|
+
stateExists,
|
|
643
|
+
tasksRootExists: taskRootExists
|
|
644
|
+
});
|
|
556
645
|
return jsonResult({
|
|
557
|
-
mode: "
|
|
646
|
+
mode: "official-openclaw-surfaces",
|
|
647
|
+
openclawHome: getOpenClawHome(),
|
|
648
|
+
openclawStateDir: getOpenClawStateDir(),
|
|
558
649
|
openclawConfigPath: configPath,
|
|
559
650
|
openclawConfigExists: exists,
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
651
|
+
openclawEnvPath: envPath,
|
|
652
|
+
openclawEnvExists: envFileExists,
|
|
653
|
+
workspaceRoot,
|
|
654
|
+
pluginEntryPresent: Boolean(pluginEntry),
|
|
655
|
+
pluginEntry,
|
|
656
|
+
pluginConfig,
|
|
657
|
+
agentPactEnvStatus,
|
|
658
|
+
summary,
|
|
563
659
|
statePath,
|
|
564
660
|
stateExists,
|
|
565
661
|
tasksRoot: taskRoot,
|
|
@@ -718,7 +814,7 @@ function register(api) {
|
|
|
718
814
|
summary: params.summary || params.title,
|
|
719
815
|
publicMaterials: params.publicMaterials
|
|
720
816
|
});
|
|
721
|
-
const triagePath = path.join(
|
|
817
|
+
const triagePath = path.join(await getWorkspaceRoot(), "agentpact", "tasks", params.taskId, "triage.json");
|
|
722
818
|
await writeJsonFile(triagePath, {
|
|
723
819
|
...triage,
|
|
724
820
|
title: params.title ?? "",
|
|
@@ -753,7 +849,7 @@ function register(api) {
|
|
|
753
849
|
const requesterComments = normalizeStringArray(params.requesterComments);
|
|
754
850
|
const classified = classifyRevisionItems(originalScope, revisionItems);
|
|
755
851
|
const recommendation = classified.scopeRisk.length > 0 ? "clarify_scope_before_full_execution" : classified.ambiguous.length > 0 ? "review_then_execute" : "execute_revision";
|
|
756
|
-
const revisionDir = path.join(
|
|
852
|
+
const revisionDir = path.join(await getWorkspaceRoot(), "agentpact", "tasks", params.taskId, "revisions", `rev-${revisionNumber}`);
|
|
757
853
|
await ensureDir(revisionDir);
|
|
758
854
|
const analysisPath = path.join(revisionDir, "analysis.md");
|
|
759
855
|
await writeMarkdown(analysisPath, [
|
|
@@ -829,7 +925,7 @@ function register(api) {
|
|
|
829
925
|
category: params.category,
|
|
830
926
|
status: "working"
|
|
831
927
|
});
|
|
832
|
-
const taskRoot =
|
|
928
|
+
const taskRoot = path.join(await getWorkspaceRoot(), "agentpact", "tasks", params.taskId);
|
|
833
929
|
const deliveryDir = path.join(taskRoot, "delivery");
|
|
834
930
|
const manifestPath = path.join(deliveryDir, "manifest.json");
|
|
835
931
|
const notesPath = path.join(deliveryDir, "notes.md");
|
|
@@ -899,7 +995,7 @@ function register(api) {
|
|
|
899
995
|
status: "confirmation_pending"
|
|
900
996
|
});
|
|
901
997
|
const review = analyzeConfirmationDelta(params);
|
|
902
|
-
const reviewPath = path.join(
|
|
998
|
+
const reviewPath = path.join(await getWorkspaceRoot(), "agentpact", "tasks", params.taskId, "confirmation-review.md");
|
|
903
999
|
await writeMarkdown(reviewPath, [
|
|
904
1000
|
"# Confirmation Review",
|
|
905
1001
|
"",
|