@hybridlabor-api/aos 4.0.2 → 4.1.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/.claude/agents/database-reviewer.md +109 -0
- package/.claude/agents/go-build-resolver.md +112 -0
- package/.claude/agents/opensource-forker.md +216 -0
- package/.claude/agents/opensource-sanitizer.md +206 -0
- package/.claude/agents/security-reviewer.md +126 -0
- package/.claude/agents/silent-failure-hunter.md +68 -0
- package/CLAUDE.md +15 -0
- package/README.md +0 -13
- package/THIRD_PARTY_NOTICES.md +133 -0
- package/package.json +4 -2
- package/skills/basic/bdbmediastorm/SKILL.md +7 -1
- package/skills/basic/startcycle/SKILL.md +2 -0
- package/skills/bdbrainstorm/SKILL.md +1 -0
- package/skills/global_config/plan-canvas/SKILL.md +233 -0
- package/skills/global_config/plan-canvas/scripts/lib/loopback-guard.js +59 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/markdown.js +301 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sdk.js +239 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +636 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sessions.js +271 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +630 -0
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +419 -0
- package/.agents/skills/firecrawl/SKILL.md +0 -149
- package/.agents/skills/firecrawl/rules/install.md +0 -82
- package/.agents/skills/firecrawl/rules/security.md +0 -26
- package/.agents/skills/firecrawl-agent/SKILL.md +0 -58
- package/.agents/skills/firecrawl-build/SKILL.md +0 -39
- package/.agents/skills/firecrawl-build-interact/SKILL.md +0 -68
- package/.agents/skills/firecrawl-build-onboarding/SKILL.md +0 -103
- package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +0 -39
- package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +0 -20
- package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +0 -17
- package/.agents/skills/firecrawl-build-scrape/SKILL.md +0 -69
- package/.agents/skills/firecrawl-build-search/SKILL.md +0 -69
- package/.agents/skills/firecrawl-crawl/SKILL.md +0 -59
- package/.agents/skills/firecrawl-download/SKILL.md +0 -70
- package/.agents/skills/firecrawl-interact/SKILL.md +0 -84
- package/.agents/skills/firecrawl-map/SKILL.md +0 -51
- package/.agents/skills/firecrawl-scrape/SKILL.md +0 -69
- package/.agents/skills/firecrawl-search/SKILL.md +0 -60
- package/docs/sessions/AUDIT-HANDOVER-2026-08-28.md +0 -169
- package/docs/sessions/BDB_REMOTEOS_MCP_HANDOVER.md +0 -130
- package/docs/sessions/SESSION-HANDOVER-v3.13.md +0 -249
- package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +0 -10
- package/mcps/after-effects-mcp/build/index.js +0 -840
- package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +0 -153
- package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +0 -218
- package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +0 -71
- package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +0 -147
- package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +0 -114
- package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +0 -115
- package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +0 -192
- package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +0 -90
- package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +0 -50
- package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +0 -1773
- package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +0 -160
- package/mcps/bdb-remoteos-mcp/queue.db +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/incus_client.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/main.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/queue.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/schemas.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/server.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/webhook.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__pycache__/mock_incus.cpython-312.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_mcp_server.cpython-312-pytest-9.1.1.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_security_redteam.cpython-312-pytest-9.1.1.pyc +0 -0
- package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_webhook.cpython-312-pytest-9.1.1.pyc +0 -0
- package/mcps/computer-use-mcp/dist/client.d.ts +0 -150
- package/mcps/computer-use-mcp/dist/client.js +0 -136
- package/mcps/computer-use-mcp/dist/entrypoint.d.ts +0 -16
- package/mcps/computer-use-mcp/dist/entrypoint.js +0 -26
- package/mcps/computer-use-mcp/dist/native.d.ts +0 -212
- package/mcps/computer-use-mcp/dist/native.js +0 -50
- package/mcps/computer-use-mcp/dist/server.d.ts +0 -32
- package/mcps/computer-use-mcp/dist/server.js +0 -342
- package/mcps/computer-use-mcp/dist/session.d.ts +0 -101
- package/mcps/computer-use-mcp/dist/session.js +0 -2372
- package/skills/bdbsaastraining/scripts/__pycache__/build_profile.cpython-314.pyc +0 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plan Canvas session store.
|
|
5
|
+
*
|
|
6
|
+
* Sessions are keyed by the canonical artifact file path so agents never
|
|
7
|
+
* juggle opaque ids. State is persisted as JSON in the Plan Canvas state
|
|
8
|
+
* dir so queued human feedback survives a server restart.
|
|
9
|
+
*
|
|
10
|
+
* Source: affaan-m/ECC — MIT, see THIRD_PARTY_NOTICES.md
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const crypto = require('crypto');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const FEEDBACK_KINDS = new Set(['chat', 'annotation', 'verdict']);
|
|
19
|
+
const VERDICTS = new Set(['approve', 'request-changes']);
|
|
20
|
+
|
|
21
|
+
function resolveStateDir(env = process.env) {
|
|
22
|
+
const override = env.AOS_PLAN_CANVAS_STATE_DIR;
|
|
23
|
+
if (override && String(override).trim()) return path.resolve(String(override).trim());
|
|
24
|
+
return path.join(os.homedir(), '.claude', 'aos-plan-canvas');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Canonicalize so `./plan.md`, symlinks, and absolute paths all land on the
|
|
28
|
+
// same session.
|
|
29
|
+
function canonicalizeArtifactPath(filePath) {
|
|
30
|
+
const absolute = path.resolve(filePath);
|
|
31
|
+
try {
|
|
32
|
+
return fs.realpathSync(absolute);
|
|
33
|
+
} catch {
|
|
34
|
+
return absolute;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function sessionKeyFor(canonicalPath) {
|
|
39
|
+
return crypto.createHash('sha256').update(canonicalPath).digest('hex').slice(0, 12);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function nowIso() {
|
|
43
|
+
return new Date().toISOString();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function sanitizeText(value, maxLength = 4000) {
|
|
47
|
+
if (typeof value !== 'string') return '';
|
|
48
|
+
return value.slice(0, maxLength);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Normalize one browser-submitted feedback item into the shape delivered to
|
|
52
|
+
// the agent. Returns null for unusable input rather than throwing so a
|
|
53
|
+
// malformed item can never wedge the queue.
|
|
54
|
+
function normalizeFeedbackItem(raw, counter) {
|
|
55
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
56
|
+
const kind = FEEDBACK_KINDS.has(raw.kind) ? raw.kind : null;
|
|
57
|
+
if (!kind) return null;
|
|
58
|
+
const item = {
|
|
59
|
+
id: `fb-${counter}`,
|
|
60
|
+
kind,
|
|
61
|
+
text: sanitizeText(raw.text),
|
|
62
|
+
at: nowIso()
|
|
63
|
+
};
|
|
64
|
+
if (kind === 'verdict') {
|
|
65
|
+
if (!VERDICTS.has(raw.verdict)) return null;
|
|
66
|
+
item.verdict = raw.verdict;
|
|
67
|
+
}
|
|
68
|
+
if (kind === 'annotation') {
|
|
69
|
+
const anchor = raw.anchor && typeof raw.anchor === 'object' ? raw.anchor : null;
|
|
70
|
+
if (!anchor || typeof anchor.selector !== 'string') return null;
|
|
71
|
+
item.anchor = {
|
|
72
|
+
selector: sanitizeText(anchor.selector, 500),
|
|
73
|
+
tag: sanitizeText(anchor.tag, 60),
|
|
74
|
+
snippet: sanitizeText(anchor.snippet, 400)
|
|
75
|
+
};
|
|
76
|
+
if (anchor.textRange && typeof anchor.textRange === 'object') {
|
|
77
|
+
item.anchor.textRange = {
|
|
78
|
+
text: sanitizeText(anchor.textRange.text, 1000)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (!item.text) return null;
|
|
82
|
+
}
|
|
83
|
+
if (kind === 'chat' && !item.text) return null;
|
|
84
|
+
return item;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function createSessionStore({ stateDir = resolveStateDir() } = {}) {
|
|
88
|
+
const stateFile = path.join(stateDir, 'sessions.json');
|
|
89
|
+
let state = { sessions: {}, feedbackCounter: 0 };
|
|
90
|
+
|
|
91
|
+
function load() {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
94
|
+
if (parsed && typeof parsed === 'object' && parsed.sessions) {
|
|
95
|
+
state = {
|
|
96
|
+
sessions: parsed.sessions,
|
|
97
|
+
feedbackCounter: Number(parsed.feedbackCounter) || 0
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
} catch {
|
|
101
|
+
// Missing or corrupt state starts fresh; queued feedback loss on a
|
|
102
|
+
// corrupt file beats refusing to start at all.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function persist() {
|
|
107
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
108
|
+
const tmpFile = `${stateFile}.tmp`;
|
|
109
|
+
fs.writeFileSync(tmpFile, JSON.stringify(state, null, 2));
|
|
110
|
+
fs.renameSync(tmpFile, stateFile);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
load();
|
|
114
|
+
|
|
115
|
+
function get(key) {
|
|
116
|
+
return state.sessions[key] || null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function findByFile(filePath) {
|
|
120
|
+
const canonical = canonicalizeArtifactPath(filePath);
|
|
121
|
+
return get(sessionKeyFor(canonical));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Open (or resume) a session. A session the *user* ended from the browser
|
|
125
|
+
// is sticky: it refuses a plain reopen so agents do not pop the browser
|
|
126
|
+
// back up uninvited. Pass reopen:true only when the human asked.
|
|
127
|
+
function open(filePath, { reopen = false } = {}) {
|
|
128
|
+
const canonical = canonicalizeArtifactPath(filePath);
|
|
129
|
+
const key = sessionKeyFor(canonical);
|
|
130
|
+
const existing = state.sessions[key];
|
|
131
|
+
if (existing && existing.status === 'ended' && existing.endedBy === 'user' && !reopen) {
|
|
132
|
+
return { session: existing, refused: true };
|
|
133
|
+
}
|
|
134
|
+
const session = existing || {
|
|
135
|
+
key,
|
|
136
|
+
file: canonical,
|
|
137
|
+
chat: [],
|
|
138
|
+
pendingFeedback: [],
|
|
139
|
+
createdAt: nowIso()
|
|
140
|
+
};
|
|
141
|
+
session.status = 'open';
|
|
142
|
+
delete session.endedBy;
|
|
143
|
+
session.updatedAt = nowIso();
|
|
144
|
+
state.sessions[key] = session;
|
|
145
|
+
persist();
|
|
146
|
+
return { session, refused: false };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Queue feedback from the browser. Chat-shaped items are mirrored into the
|
|
150
|
+
// session transcript immediately so the conversation panel stays coherent
|
|
151
|
+
// across reloads.
|
|
152
|
+
function queueFeedback(key, rawItems, { endSession = false } = {}) {
|
|
153
|
+
const session = get(key);
|
|
154
|
+
if (!session || session.status === 'ended') return null;
|
|
155
|
+
const accepted = [];
|
|
156
|
+
for (const raw of Array.isArray(rawItems) ? rawItems : []) {
|
|
157
|
+
state.feedbackCounter += 1;
|
|
158
|
+
const item = normalizeFeedbackItem(raw, state.feedbackCounter);
|
|
159
|
+
if (item) accepted.push(item);
|
|
160
|
+
}
|
|
161
|
+
session.pendingFeedback.push(...accepted);
|
|
162
|
+
for (const item of accepted) {
|
|
163
|
+
session.chat.push({ role: 'user', kind: item.kind, text: chatLineFor(item), at: item.at });
|
|
164
|
+
}
|
|
165
|
+
if (endSession) {
|
|
166
|
+
session.status = 'ended';
|
|
167
|
+
session.endedBy = 'user';
|
|
168
|
+
} else if (accepted.length > 0) {
|
|
169
|
+
session.status = 'feedback';
|
|
170
|
+
}
|
|
171
|
+
session.updatedAt = nowIso();
|
|
172
|
+
persist();
|
|
173
|
+
return { accepted, pending: session.pendingFeedback.length, session };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Deliver-and-drain: feedback is handed to exactly one await call, after
|
|
177
|
+
// which the session flips back to open. An ended session keeps reporting
|
|
178
|
+
// ended (with attribution) so agents know to stop polling.
|
|
179
|
+
function takeFeedback(key) {
|
|
180
|
+
const session = get(key);
|
|
181
|
+
if (!session) return { status: 'missing' };
|
|
182
|
+
if (session.pendingFeedback.length > 0) {
|
|
183
|
+
const items = session.pendingFeedback;
|
|
184
|
+
session.pendingFeedback = [];
|
|
185
|
+
const result = { status: 'feedback', items };
|
|
186
|
+
if (session.status === 'ended') {
|
|
187
|
+
result.sessionEnded = true;
|
|
188
|
+
result.endedBy = session.endedBy;
|
|
189
|
+
} else {
|
|
190
|
+
session.status = 'open';
|
|
191
|
+
}
|
|
192
|
+
session.updatedAt = nowIso();
|
|
193
|
+
persist();
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
if (session.status === 'ended') {
|
|
197
|
+
return { status: 'ended', endedBy: session.endedBy };
|
|
198
|
+
}
|
|
199
|
+
return { status: 'waiting' };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function addAgentReply(key, text) {
|
|
203
|
+
const session = get(key);
|
|
204
|
+
if (!session) return null;
|
|
205
|
+
const entry = { role: 'agent', kind: 'chat', text: sanitizeText(text), at: nowIso() };
|
|
206
|
+
session.chat.push(entry);
|
|
207
|
+
session.updatedAt = nowIso();
|
|
208
|
+
persist();
|
|
209
|
+
return entry;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function end(key, endedBy) {
|
|
213
|
+
const session = get(key);
|
|
214
|
+
if (!session) return null;
|
|
215
|
+
session.status = 'ended';
|
|
216
|
+
session.endedBy = endedBy === 'user' ? 'user' : 'agent';
|
|
217
|
+
session.updatedAt = nowIso();
|
|
218
|
+
persist();
|
|
219
|
+
return session;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function list() {
|
|
223
|
+
return Object.values(state.sessions).map(session => ({
|
|
224
|
+
key: session.key,
|
|
225
|
+
file: session.file,
|
|
226
|
+
status: session.status,
|
|
227
|
+
endedBy: session.endedBy,
|
|
228
|
+
pending: session.pendingFeedback.length,
|
|
229
|
+
updatedAt: session.updatedAt
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function hasOpenSessions() {
|
|
234
|
+
return Object.values(state.sessions).some(session => session.status !== 'ended');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
stateDir,
|
|
239
|
+
stateFile,
|
|
240
|
+
open,
|
|
241
|
+
get,
|
|
242
|
+
findByFile,
|
|
243
|
+
queueFeedback,
|
|
244
|
+
takeFeedback,
|
|
245
|
+
addAgentReply,
|
|
246
|
+
end,
|
|
247
|
+
list,
|
|
248
|
+
hasOpenSessions
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// One-line rendering of a feedback item for the conversation transcript.
|
|
253
|
+
function chatLineFor(item) {
|
|
254
|
+
if (item.kind === 'verdict') {
|
|
255
|
+
const label = item.verdict === 'approve' ? 'Approved the plan' : 'Requested changes';
|
|
256
|
+
return item.text ? `${label}: ${item.text}` : label;
|
|
257
|
+
}
|
|
258
|
+
if (item.kind === 'annotation') {
|
|
259
|
+
const where = item.anchor.snippet || item.anchor.selector;
|
|
260
|
+
return `[${where}] ${item.text}`;
|
|
261
|
+
}
|
|
262
|
+
return item.text;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
canonicalizeArtifactPath,
|
|
267
|
+
createSessionStore,
|
|
268
|
+
normalizeFeedbackItem,
|
|
269
|
+
resolveStateDir,
|
|
270
|
+
sessionKeyFor
|
|
271
|
+
};
|