@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.
Files changed (79) hide show
  1. package/.claude/agents/database-reviewer.md +109 -0
  2. package/.claude/agents/go-build-resolver.md +112 -0
  3. package/.claude/agents/opensource-forker.md +216 -0
  4. package/.claude/agents/opensource-sanitizer.md +206 -0
  5. package/.claude/agents/security-reviewer.md +126 -0
  6. package/.claude/agents/silent-failure-hunter.md +68 -0
  7. package/CLAUDE.md +15 -0
  8. package/README.md +0 -13
  9. package/THIRD_PARTY_NOTICES.md +133 -0
  10. package/package.json +4 -2
  11. package/skills/basic/bdbmediastorm/SKILL.md +7 -1
  12. package/skills/basic/startcycle/SKILL.md +2 -0
  13. package/skills/bdbrainstorm/SKILL.md +1 -0
  14. package/skills/global_config/plan-canvas/SKILL.md +233 -0
  15. package/skills/global_config/plan-canvas/scripts/lib/loopback-guard.js +59 -0
  16. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/markdown.js +301 -0
  17. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sdk.js +239 -0
  18. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +636 -0
  19. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sessions.js +271 -0
  20. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +630 -0
  21. package/skills/global_config/plan-canvas/scripts/plan-canvas.js +419 -0
  22. package/.agents/skills/firecrawl/SKILL.md +0 -149
  23. package/.agents/skills/firecrawl/rules/install.md +0 -82
  24. package/.agents/skills/firecrawl/rules/security.md +0 -26
  25. package/.agents/skills/firecrawl-agent/SKILL.md +0 -58
  26. package/.agents/skills/firecrawl-build/SKILL.md +0 -39
  27. package/.agents/skills/firecrawl-build-interact/SKILL.md +0 -68
  28. package/.agents/skills/firecrawl-build-onboarding/SKILL.md +0 -103
  29. package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +0 -39
  30. package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +0 -20
  31. package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +0 -17
  32. package/.agents/skills/firecrawl-build-scrape/SKILL.md +0 -69
  33. package/.agents/skills/firecrawl-build-search/SKILL.md +0 -69
  34. package/.agents/skills/firecrawl-crawl/SKILL.md +0 -59
  35. package/.agents/skills/firecrawl-download/SKILL.md +0 -70
  36. package/.agents/skills/firecrawl-interact/SKILL.md +0 -84
  37. package/.agents/skills/firecrawl-map/SKILL.md +0 -51
  38. package/.agents/skills/firecrawl-scrape/SKILL.md +0 -69
  39. package/.agents/skills/firecrawl-search/SKILL.md +0 -60
  40. package/docs/sessions/AUDIT-HANDOVER-2026-08-28.md +0 -169
  41. package/docs/sessions/BDB_REMOTEOS_MCP_HANDOVER.md +0 -130
  42. package/docs/sessions/SESSION-HANDOVER-v3.13.md +0 -249
  43. package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +0 -10
  44. package/mcps/after-effects-mcp/build/index.js +0 -840
  45. package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +0 -153
  46. package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +0 -218
  47. package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +0 -71
  48. package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +0 -147
  49. package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +0 -114
  50. package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +0 -115
  51. package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +0 -192
  52. package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +0 -90
  53. package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +0 -50
  54. package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +0 -1773
  55. package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +0 -160
  56. package/mcps/bdb-remoteos-mcp/queue.db +0 -0
  57. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
  58. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/incus_client.cpython-312.pyc +0 -0
  59. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/main.cpython-312.pyc +0 -0
  60. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/queue.cpython-312.pyc +0 -0
  61. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/schemas.cpython-312.pyc +0 -0
  62. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/server.cpython-312.pyc +0 -0
  63. package/mcps/bdb-remoteos-mcp/src/bdb_remoteos_mcp/__pycache__/webhook.cpython-312.pyc +0 -0
  64. package/mcps/bdb-remoteos-mcp/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  65. package/mcps/bdb-remoteos-mcp/tests/__pycache__/mock_incus.cpython-312.pyc +0 -0
  66. package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_mcp_server.cpython-312-pytest-9.1.1.pyc +0 -0
  67. package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_security_redteam.cpython-312-pytest-9.1.1.pyc +0 -0
  68. package/mcps/bdb-remoteos-mcp/tests/__pycache__/test_webhook.cpython-312-pytest-9.1.1.pyc +0 -0
  69. package/mcps/computer-use-mcp/dist/client.d.ts +0 -150
  70. package/mcps/computer-use-mcp/dist/client.js +0 -136
  71. package/mcps/computer-use-mcp/dist/entrypoint.d.ts +0 -16
  72. package/mcps/computer-use-mcp/dist/entrypoint.js +0 -26
  73. package/mcps/computer-use-mcp/dist/native.d.ts +0 -212
  74. package/mcps/computer-use-mcp/dist/native.js +0 -50
  75. package/mcps/computer-use-mcp/dist/server.d.ts +0 -32
  76. package/mcps/computer-use-mcp/dist/server.js +0 -342
  77. package/mcps/computer-use-mcp/dist/session.d.ts +0 -101
  78. package/mcps/computer-use-mcp/dist/session.js +0 -2372
  79. 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
+ };