@crewx/sdk 0.8.0-rc.80 → 0.8.0-rc.83
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/dist/__tests__/adapter/context-builder.test.d.ts +1 -0
- package/dist/__tests__/adapter/plugin-helper.test.d.ts +1 -0
- package/dist/__tests__/adapter/registration-integration.test.d.ts +1 -0
- package/dist/__tests__/adapter/scoped-store.test.d.ts +1 -0
- package/dist/__tests__/plugins/conversation.test.d.ts +1 -0
- package/dist/__tests__/testing/createMockContext.test.d.ts +1 -0
- package/dist/adapter/context-builder.d.ts +0 -9
- package/dist/adapter/index.d.ts +0 -1
- package/dist/adapter/plugin-helper.d.ts +0 -7
- package/dist/adapter/scoped-store.d.ts +0 -10
- package/dist/adapter/types.d.ts +0 -7
- package/dist/agent/resolver.d.ts +0 -13
- package/dist/boxing/box-storage.interface.d.ts +0 -4
- package/dist/boxing/box.service.d.ts +0 -4
- package/dist/boxing/box.types.d.ts +0 -4
- package/dist/boxing/context-builder.d.ts +0 -4
- package/dist/client/CrewxClient.d.ts +0 -32
- package/dist/client/index.d.ts +0 -1
- package/dist/client/index.js +1 -6
- package/dist/config/loader.browser.d.ts +0 -8
- package/dist/config/loader.d.ts +0 -12
- package/dist/conversation/__tests__/sqlite-provider.test.d.ts +1 -0
- package/dist/conversation/__tests__/to-task-reader.test.d.ts +1 -0
- package/dist/conversation/index.d.ts +0 -1
- package/dist/conversation/sqlite-provider.d.ts +0 -9
- package/dist/conversation/to-task-reader.d.ts +0 -11
- package/dist/conversation/to-template-messages.d.ts +0 -13
- package/dist/conversation/types.d.ts +0 -58
- package/dist/esm/client/index.js +1 -0
- package/dist/esm/hooks/index.js +7 -0
- package/dist/esm/index.js +79 -0
- package/dist/esm/plugins/index.js +52 -0
- package/dist/esm/testing/index.js +1 -0
- package/dist/esm/tools/node/index.js +36 -0
- package/dist/events/TypedEventEmitter.d.ts +0 -24
- package/dist/events/types.d.ts +0 -43
- package/dist/facade/Crewx.browser.d.ts +0 -40
- package/dist/facade/Crewx.d.ts +0 -163
- package/dist/hooks/define.d.ts +0 -1
- package/dist/hooks/dispatch.d.ts +0 -12
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.js +7 -24
- package/dist/hooks/observer.d.ts +0 -1
- package/dist/hooks/plugin.d.ts +0 -1
- package/dist/hooks/tool-normalize.d.ts +0 -26
- package/dist/hooks/types.d.ts +0 -1
- package/dist/hooks/yaml-plugin.d.ts +0 -1
- package/dist/index.browser.d.ts +0 -7
- package/dist/index.browser.js +2 -25
- package/dist/index.d.ts +0 -4
- package/dist/index.js +79 -151
- package/dist/layout/loader.d.ts +0 -20
- package/dist/layout/props-validator.d.ts +0 -6
- package/dist/layout/renderer.d.ts +0 -24
- package/dist/layout/types.d.ts +0 -42
- package/dist/parallel/agent-runtime.d.ts +0 -11
- package/dist/parallel/helpers.d.ts +0 -1
- package/dist/parallel/index.d.ts +0 -1
- package/dist/parallel/parallel-runner.d.ts +0 -8
- package/dist/parallel/types.d.ts +0 -24
- package/dist/parsers/agent-call.util.d.ts +0 -3
- package/dist/parsers/claude.parser.d.ts +0 -8
- package/dist/parsers/codex.parser.d.ts +0 -8
- package/dist/parsers/copilot.parser.d.ts +0 -9
- package/dist/parsers/gemini.parser.d.ts +0 -10
- package/dist/parsers/opencode.parser.d.ts +0 -10
- package/dist/parsers/router.d.ts +0 -5
- package/dist/paths.d.ts +1 -0
- package/dist/platform/BrowserFsAdapter.d.ts +0 -20
- package/dist/platform/IFsAdapter.d.ts +0 -23
- package/dist/platform/NodeFsAdapter.d.ts +0 -8
- package/dist/plugin/plugin-provider.d.ts +0 -22
- package/dist/plugin/types.d.ts +0 -31
- package/dist/plugin.d.ts +0 -27
- package/dist/plugins/conversation.d.ts +0 -2
- package/dist/plugins/file-logger.d.ts +0 -13
- package/dist/plugins/index.d.ts +0 -10
- package/dist/plugins/index.js +52 -19
- package/dist/plugins/sqlite-tracing.d.ts +0 -13
- package/dist/plugins/sqlite-tracing.spec.d.ts +1 -0
- package/dist/provider/bridge.browser.d.ts +0 -20
- package/dist/provider/bridge.d.ts +0 -47
- package/dist/provider/parse-usage.d.ts +0 -14
- package/dist/provider/register-api.d.ts +0 -7
- package/dist/provider/vercel-runtime.d.ts +0 -29
- package/dist/remote/index.d.ts +0 -6
- package/dist/remote/remote-agent-manager.d.ts +0 -31
- package/dist/remote/remote-provider.d.ts +0 -15
- package/dist/remote/remote-transport.d.ts +0 -17
- package/dist/remote/types.d.ts +0 -59
- package/dist/server/auth.d.ts +0 -16
- package/dist/server/handler.d.ts +0 -17
- package/dist/server/index.d.ts +0 -4
- package/dist/server/tool-adapter.d.ts +0 -16
- package/dist/template/engine.d.ts +0 -19
- package/dist/template/helpers/exec.browser.d.ts +0 -7
- package/dist/template/helpers/exec.d.ts +0 -45
- package/dist/template/helpers/fenced_code.d.ts +0 -16
- package/dist/template/helpers/format-conversation.d.ts +0 -22
- package/dist/template/helpers/include.d.ts +0 -15
- package/dist/template/helpers/p1p2.d.ts +0 -32
- package/dist/template/loader/DocumentLoader.d.ts +0 -30
- package/dist/template/types.d.ts +0 -30
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +1 -16
- package/dist/testing/mock-audit.d.ts +0 -1
- package/dist/testing/mock-context.d.ts +0 -1
- package/dist/testing/mock-logger.d.ts +0 -1
- package/dist/testing/mock-router.d.ts +0 -1
- package/dist/testing/mock-storage.d.ts +0 -1
- package/dist/testing/mock-store.d.ts +0 -1
- package/dist/tools/delegate.d.ts +0 -7
- package/dist/tools/index.d.ts +0 -4
- package/dist/tools/node/builtin.d.ts +0 -16
- package/dist/tools/node/index.d.ts +0 -20
- package/dist/tools/node/index.js +36 -59
- package/dist/types/index.d.ts +0 -20
- package/dist/types/task-log.types.d.ts +0 -4
- package/dist/utils/env-defaults.d.ts +0 -16
- package/dist/utils/glob-match.d.ts +0 -16
- package/dist/utils/id.d.ts +0 -15
- package/dist/utils/timestamp.d.ts +0 -1
- package/dist/utils/workspace.d.ts +0 -4
- package/package.json +24 -25
- package/dist/adapter/context-builder.js +0 -87
- package/dist/adapter/index.js +0 -21
- package/dist/adapter/plugin-helper.js +0 -45
- package/dist/adapter/scoped-store.js +0 -43
- package/dist/adapter/types.js +0 -23
- package/dist/agent/resolver.js +0 -46
- package/dist/boxing/box-storage.interface.js +0 -6
- package/dist/boxing/box.service.js +0 -73
- package/dist/boxing/box.types.js +0 -6
- package/dist/boxing/context-builder.js +0 -79
- package/dist/client/CrewxClient.js +0 -86
- package/dist/config/loader.browser.js +0 -59
- package/dist/config/loader.js +0 -95
- package/dist/conversation/index.js +0 -25
- package/dist/conversation/sqlite-provider.js +0 -178
- package/dist/conversation/to-task-reader.js +0 -28
- package/dist/conversation/to-template-messages.js +0 -34
- package/dist/conversation/types.js +0 -10
- package/dist/events/TypedEventEmitter.js +0 -65
- package/dist/events/types.js +0 -9
- package/dist/facade/Crewx.browser.js +0 -314
- package/dist/facade/Crewx.js +0 -1299
- package/dist/hooks/define.js +0 -13
- package/dist/hooks/dispatch.js +0 -147
- package/dist/hooks/observer.js +0 -60
- package/dist/hooks/plugin.js +0 -17
- package/dist/hooks/tool-normalize.js +0 -110
- package/dist/hooks/types.js +0 -12
- package/dist/hooks/yaml-plugin.js +0 -356
- package/dist/layout/loader.js +0 -305
- package/dist/layout/props-validator.js +0 -301
- package/dist/layout/renderer.js +0 -193
- package/dist/layout/types.js +0 -36
- package/dist/parallel/agent-runtime.js +0 -25
- package/dist/parallel/helpers.js +0 -219
- package/dist/parallel/index.js +0 -13
- package/dist/parallel/parallel-runner.js +0 -226
- package/dist/parallel/types.js +0 -6
- package/dist/parsers/agent-call.util.js +0 -19
- package/dist/parsers/claude.parser.js +0 -67
- package/dist/parsers/codex.parser.js +0 -100
- package/dist/parsers/copilot.parser.js +0 -66
- package/dist/parsers/gemini.parser.js +0 -46
- package/dist/parsers/opencode.parser.js +0 -76
- package/dist/parsers/router.js +0 -56
- package/dist/platform/BrowserFsAdapter.js +0 -84
- package/dist/platform/IFsAdapter.js +0 -3
- package/dist/platform/NodeFsAdapter.js +0 -38
- package/dist/plugin/plugin-provider.js +0 -207
- package/dist/plugin/types.js +0 -9
- package/dist/plugin.js +0 -29
- package/dist/plugins/conversation.js +0 -59
- package/dist/plugins/file-logger.js +0 -87
- package/dist/plugins/sqlite-tracing.js +0 -112
- package/dist/provider/bridge.browser.js +0 -49
- package/dist/provider/bridge.js +0 -381
- package/dist/provider/parse-usage.js +0 -83
- package/dist/provider/register-api.js +0 -24
- package/dist/provider/vercel-runtime.js +0 -347
- package/dist/remote/index.js +0 -32
- package/dist/remote/remote-agent-manager.js +0 -198
- package/dist/remote/remote-provider.js +0 -141
- package/dist/remote/remote-transport.js +0 -83
- package/dist/remote/types.js +0 -9
- package/dist/server/auth.js +0 -35
- package/dist/server/handler.js +0 -75
- package/dist/server/index.js +0 -9
- package/dist/server/tool-adapter.js +0 -95
- package/dist/template/engine.js +0 -137
- package/dist/template/helpers/exec.browser.js +0 -41
- package/dist/template/helpers/exec.js +0 -230
- package/dist/template/helpers/fenced_code.js +0 -20
- package/dist/template/helpers/format-conversation.js +0 -53
- package/dist/template/helpers/include.js +0 -23
- package/dist/template/helpers/p1p2.js +0 -90
- package/dist/template/loader/DocumentLoader.js +0 -128
- package/dist/template/types.js +0 -6
- package/dist/testing/mock-audit.js +0 -13
- package/dist/testing/mock-context.js +0 -68
- package/dist/testing/mock-logger.js +0 -27
- package/dist/testing/mock-router.js +0 -67
- package/dist/testing/mock-storage.js +0 -21
- package/dist/testing/mock-store.js +0 -8
- package/dist/tools/delegate.js +0 -60
- package/dist/tools/index.js +0 -9
- package/dist/tools/node/builtin.js +0 -547
- package/dist/types/index.js +0 -32
- package/dist/types/task-log.types.js +0 -6
- package/dist/utils/env-defaults.js +0 -27
- package/dist/utils/glob-match.js +0 -42
- package/dist/utils/id.js +0 -50
- package/dist/utils/timestamp.js +0 -13
- package/dist/utils/workspace.js +0 -58
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {existsSync,mkdirSync,writeFileSync,appendFileSync}from'fs';import*as x from'path';import {join,dirname,basename}from'path';import {homedir}from'os';import $ from'better-sqlite3';import {createHash}from'crypto';var d=class{detach(s){}};function S(i){let s=t=>String(t).padStart(2,"0");return `${i.getFullYear()}${s(i.getMonth()+1)}${s(i.getDate())}T${s(i.getHours())}${s(i.getMinutes())}${s(i.getSeconds())}`}var h=class extends d{name="file-logger";unsubs=[];logFiles=new Map;logsDir;version;constructor(s){super(),this.logsDir=join(s?.workspaceRoot??process.cwd(),".crewx","logs"),this.version=s?.version??"unknown";}attach(s){this.unsubs.push(s.on("task:start",t=>{try{existsSync(this.logsDir)||mkdirSync(this.logsDir,{recursive:!0});let r=S(t.timestamp),a=join(this.logsDir,`${r}_${t.traceId}.log`);this.logFiles.set(t.traceId,a);let n=`=== TASK LOG: ${t.traceId} ===
|
|
2
|
+
CrewX Version: ${this.version}
|
|
3
|
+
Mode: ${t.mode}
|
|
4
|
+
Agent: ${t.agentRef}
|
|
5
|
+
Started: ${t.timestamp.toLocaleString()}
|
|
6
|
+
Message: ${t.message}
|
|
7
|
+
|
|
8
|
+
`;writeFileSync(a,n,{encoding:"utf8",mode:384});}catch{}}),s.on("task:output",t=>{try{let r=this.logFiles.get(t.traceId);if(!r)return;let a=new Date().toISOString();appendFileSync(r,`[${a}] STDOUT: ${t.output}
|
|
9
|
+
`,"utf8");}catch{}}),s.on("task:end",t=>{try{let r=this.logFiles.get(t.traceId);if(!r)return;let a=new Date().toLocaleString(),n=t.error?`failed: ${t.error.message}`:"completed successfully",p=`[${a}] INFO: Task ${n} in ${t.durationMs}ms
|
|
10
|
+
[${a}] INFO: Process closed with exit code: ${t.error?1:0}
|
|
11
|
+
`;appendFileSync(r,p,"utf8"),this.logFiles.delete(t.traceId);}catch{}}));}detach(s){this.unsubs.forEach(t=>t()),this.unsubs=[],this.logFiles.clear();}};function P(i){let s=x.resolve(i);return process.platform==="win32"&&(s=s.replace(/\\/g,"/"),s=s.replace(/^([A-Z]):/,(t,r)=>`${r.toLowerCase()}:`)),s.length>1&&!/^[a-zA-Z]:\/$/.test(s)&&(s=s.replace(/\/+$/,"")),s}function C(i){let s=P(i);return createHash("sha256").update(s).digest("hex")}var T=class extends d{name="sqlite-tracing";db=null;unsubs=[];dbPath;version;constructor(s){super(),this.dbPath=join(s?.dbRoot??homedir(),".crewx","crewx.db"),this.version=s?.version??"unknown";}attach(s){let t=dirname(this.dbPath);existsSync(t)||mkdirSync(t,{recursive:true}),this.db=new $(this.dbPath);let r=this.db.prepare("PRAGMA table_info(tasks)").all(),a=e=>r.some(o=>o.name===e);a("parent_task_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN parent_task_id TEXT"),a("caller_agent_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN caller_agent_id TEXT"),a("trace_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN trace_id TEXT");let n=process.cwd(),p=existsSync(join(n,"crewx.yaml"))||existsSync(join(n,"crewx.yml")),w=p?C(n):null,g=p?basename(n):null,f=process.argv.join(" ");this.unsubs.push(s.on("task:start",e=>{try{let o=process.env.CREWX_CALLER_AGENT_ID||null,u=process.env.CREWX_PARENT_TASK_ID||null,v=process.env.CREWX_TRACE_ID||e.traceId,I=e.metadata?JSON.stringify(e.metadata):JSON.stringify({provider:e.provider??"cli/claude"});this.db.prepare(`INSERT OR IGNORE INTO tasks
|
|
12
|
+
(id, agent_id, prompt, mode, status, pid, started_at,
|
|
13
|
+
crewx_version, platform,
|
|
14
|
+
model, rendered_prompt, command, coding_agent_command,
|
|
15
|
+
workspace_id, workspace_name,
|
|
16
|
+
caller_agent_id, parent_task_id, trace_id, metadata, thread_id)
|
|
17
|
+
VALUES (?, ?, ?, ?, 'running', ?, ?,
|
|
18
|
+
?, ?,
|
|
19
|
+
?, ?, ?, ?,
|
|
20
|
+
?, ?,
|
|
21
|
+
?, ?, ?, ?, ?)`).run(e.traceId,e.agentRef.replace(/^@/,""),e.message,e.mode,e.pid??null,e.timestamp.toISOString(),this.version,e.platform??"cli",e.model??null,e.renderedPrompt??null,f,e.codingAgentCommand??null,e.workspaceId??w,e.workspaceName??g,o,u,v,I,e.threadId??null);}catch{}}),s.on("task:output",e=>{try{let o=this.db.prepare("SELECT logs FROM tasks WHERE id=?").get(e.traceId),u=o?.logs?JSON.parse(o.logs):[];u.push({timestamp:e.timestamp.toISOString(),level:e.level??"stdout",message:e.output}),this.db.prepare("UPDATE tasks SET logs=? WHERE id=?").run(JSON.stringify(u),e.traceId);}catch{}}),s.on("task:end",e=>{try{let o=e.error?"failed":"success";this.db.prepare(`UPDATE tasks
|
|
22
|
+
SET status=?, result=?, error=?,
|
|
23
|
+
completed_at=?, duration_ms=?,
|
|
24
|
+
exit_code=?,
|
|
25
|
+
input_tokens=?, output_tokens=?, cached_input_tokens=?,
|
|
26
|
+
cost_usd=?,
|
|
27
|
+
model=COALESCE(?, model)
|
|
28
|
+
WHERE id=?`).run(o,e.result??null,e.error?JSON.stringify(e.error):null,e.timestamp.toISOString(),e.durationMs,e.exitCode??null,e.inputTokens??0,e.outputTokens??0,e.cachedInputTokens??0,e.costUsd??0,e.model??null,e.traceId);}catch{}}));}detach(s){this.unsubs.forEach(t=>t()),this.unsubs=[],this.db?.close(),this.db=null;}};var X=`
|
|
29
|
+
CREATE TABLE IF NOT EXISTS threads (
|
|
30
|
+
id TEXT PRIMARY KEY,
|
|
31
|
+
workspace_id TEXT,
|
|
32
|
+
platform TEXT NOT NULL DEFAULT 'cli',
|
|
33
|
+
title TEXT,
|
|
34
|
+
first_message TEXT,
|
|
35
|
+
last_message TEXT,
|
|
36
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
37
|
+
created_at TEXT NOT NULL,
|
|
38
|
+
updated_at TEXT NOT NULL,
|
|
39
|
+
metadata TEXT
|
|
40
|
+
)
|
|
41
|
+
`,q=["id","thread_id","prompt","result","started_at","trace_id","status","parent_task_id","agent_id"];function j(i){return i.replace(/<conversation_history[^>]*>[\s\S]*?<\/conversation_history>/g,"").split(`
|
|
42
|
+
`).filter(a=>!(a.startsWith("Loaded ")&&a.includes("layouts from")||a.includes("[dotenv@")||a.includes("[Nest]")&&a.includes("DEBUG")||a.startsWith("Registered custom layout:")||a.startsWith("Updated custom layout:"))).join(`
|
|
43
|
+
`).trim()}function B(i){if(!i)return "";let s=i;try{let t=JSON.parse(s);Array.isArray(t)?s=t.filter(r=>r?.type==="text"&&r?.text).map(r=>r.text).join(`
|
|
44
|
+
`):t&&typeof t=="object"&&t.result!==void 0&&(s=t.result||"");}catch{s=j(s);}return s}var m=class{db;constructor(s){let t=s??join(homedir(),".crewx","crewx.db");this.db=new $(t),this.init();}init(){this.db.pragma("journal_mode = WAL"),this.db.exec(X);}async ensureThread(s,t,r){let a=this.db.prepare("SELECT platform FROM threads WHERE id = ?").get(s);if(a){if(a.platform!==t)throw new Error(`Thread '${s}' already exists with platform '${a.platform}' \u2014 cannot change to '${t}' (platform is immutable)`);r&&this.db.prepare("UPDATE threads SET workspace_id = COALESCE(workspace_id, ?) WHERE id = ?").run(r,s);return}let n=new Date().toISOString();this.db.prepare("INSERT INTO threads (id, platform, workspace_id, message_count, created_at, updated_at) VALUES (?, ?, ?, 0, ?, ?)").run(s,t,r??null,n,n);}async fetchHistory(s,t){let r=t?.limit??100,a=["thread_id = ?","(parent_task_id IS NULL OR parent_task_id = '')","(status IN ('done', 'completed', 'success') OR status IS NULL)"],n=[s];t?.currentTraceId&&(a.push("trace_id != ?"),n.push(t.currentTraceId));let p=a.join(" AND "),g=`SELECT ${q.join(", ")} FROM tasks WHERE ${p} ORDER BY started_at ASC LIMIT ?`;n.push(r);let f=this.db.prepare(g).all(...n),e=this.db.prepare("SELECT platform, title, first_message, last_message, message_count, updated_at FROM threads WHERE id = ?").get(s),o=e?.platform??"cli",u=this.rowsToMessages(f);return {threadId:s,platform:o,messages:u,metadata:{title:e?.title??void 0,firstMessage:e?.first_message??void 0,lastMessage:e?.last_message??void 0,messageCount:e?.message_count??0,updatedAt:e?.updated_at?new Date(e.updated_at).getTime():void 0}}}async saveUserMessage(s,t,r,a){let n=new Date().toISOString();this.db.prepare(`UPDATE threads
|
|
45
|
+
SET first_message = COALESCE(first_message, ?),
|
|
46
|
+
last_message = ?,
|
|
47
|
+
message_count = message_count + 1,
|
|
48
|
+
updated_at = ?
|
|
49
|
+
WHERE id = ?`).run(t,t,n,s);}async saveAssistantMessage(s,t,r,a){let n=new Date().toISOString();this.db.prepare(`UPDATE threads
|
|
50
|
+
SET last_message = ?,
|
|
51
|
+
updated_at = ?
|
|
52
|
+
WHERE id = ?`).run(t,n,s);}close(){this.db.close();}rowsToMessages(s){let t=[];for(let r of s){r.prompt&&t.push({id:`${r.id}-user`,text:r.prompt,isAssistant:false,timestamp:new Date(r.started_at).getTime()});let a=B(r.result);a&&t.push({id:`${r.id}-assistant`,text:a,isAssistant:true,timestamp:new Date(r.started_at).getTime()});}return t}};var y=class extends d{name="conversation";_provider;unsubStart=null;unsubEnd=null;constructor(s){super(),this._provider=new m(s?.dbPath);}get conversationProvider(){return this._provider}attach(s){this.unsubStart=s.on("task:start",async t=>{if(!t.threadId)return;let r=t.platform??"cli";try{await this._provider.ensureThread(t.threadId,r,t.workspaceId),await this._provider.saveUserMessage(t.threadId,t.message??"");}catch{}}),this.unsubEnd=s.on("task:end",async t=>{if(!t.result)return;let r=t.metadata?.threadId;if(!r)return;let a=t.agentRef?.replace(/^@/,"")??"";try{await this._provider.saveAssistantMessage(r,t.result,a);}catch{}});}detach(s){this.unsubStart?.(),this.unsubStart=null,this.unsubEnd?.(),this.unsubEnd=null,this._provider.close?.();}};export{y as ConversationPlugin,h as FileLoggerPlugin,T as SqliteTracingPlugin};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function y(){let e=[];return {events:e,async log(t,r){e.push({event:t,payload:r});}}}function R(){let e={debug:[],info:[],warn:[],error:[]};return {entries:e,debug(t,r){e.debug.push({msg:t,meta:r});},info(t,r){e.info.push({msg:t,meta:r});},warn(t,r){e.warn.push({msg:t,meta:r});},error(t,r){e.error.push({msg:t,meta:r});}}}function E(){let e=200,t,r,n={},o={status(s){return e=s,o},set(s,i){return n[s]=i,o},send(s){return r=s,o},json(s){return t=s,o},end(){return o},getStatusCode:()=>e,getJsonBody:()=>t,getSentBody:()=>r,getHeaders:()=>({...n})};return o}function k(){let e=[];return {routes:e,registerRoute(r,n,o){e.push({path:r,handler:n,opts:o});},async simulate(r,n,o=Buffer.alloc(0),s={},i={},p={}){let d=e.find(m=>m.path===n);if(!d)return {status:404,body:{error:"Not found"},headers:{}};let f={method:r,url:n,headers:s,body:o,params:i,query:p},u=E();return await d.handler(f,u),{status:u.getStatusCode(),body:u.getJsonBody()??u.getSentBody(),headers:u.getHeaders()}}}}function b(e){let t=new Map,r=n=>n.startsWith(`${e}::`)?n:`${e}::${n}`;return {async get(n){let o=t.get(r(n));return o?o.value:void 0},async set(n,o){t.set(r(n),{value:o});},async delete(n){return t.delete(r(n))},async list(n){let o=n?r(n):`${e}::`,s=[];for(let i of t.keys())i.startsWith(o)&&s.push(i.slice(e.length+2));return s}}}function l(e){return b(e)}function M(){let e=new Map;return {blobs:e,async put(t,r,n){return e.set(t,{data:r,contentType:n}),t},async get(t){let r=e.get(t);return r?r.data:void 0},async delete(t){return e.delete(t)}}}function P(e){let t=e.instanceId??"mock-instance",r=y(),n=R(),o=k(),s=l(t),i=M(),p=[],d=[],f=[],u={run:async()=>({output:""}),...e.agentRunner},m=new AbortController,x=async a=>(p.push(a),{accepted:true}),S=async a=>(d.push(a),{accepted:true}),w=async(a,h)=>{f.push({messageId:a,patch:h});},A=async a=>({userId:a,displayName:a}),v=async()=>{},C=async()=>({messageId:"mock-proactive",sentAt:Date.now()});return {instanceId:t,installationId:e.installationId,config:e.config,capabilities:new Set(e.capabilities??[]),log:n,agentRunner:u,db:s,storage:i,audit:r,abortSignal:e.abortSignal??m.signal,httpRouter:o,router:o,inbound:x,emitEvent:S,updateMessage:w,resolveUser:A,respondSync:v,proactive:C,inboundCalls:p,emittedEvents:d,sentMessages:f}}export{y as createMockAudit,P as createMockContext,R as createMockLogger,k as createMockRouter,M as createMockStorage,l as createMockStore};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import p from'path';import u from'fs/promises';import {exec}from'child_process';import {promisify}from'util';var F=promisify(exec),g=new Set(["node_modules",".git","dist","build",".next"]);async function $(r,s,o=5,t=0){if(t>=o)return [`${p.relative(s,r)}/ (max depth reached)`];let e=[],n;try{n=await u.readdir(r,{withFileTypes:!0});}catch{return [`${p.relative(s,r)}/ (permission denied)`]}for(let c of n){let i=p.join(r,c.name),a=p.relative(s,i);if(c.isDirectory()){e.push(`${a}/`);let l=await $(i,s,o,t+1);e.push(...l);}else {let l=await u.stat(i);e.push(`${a} (${l.size} bytes)`);}}return e}async function x(r,s){let{currentDepth:o,maxDepth:t}=s,e=" ".repeat(o),n;try{n=await u.readdir(r,{withFileTypes:!0});}catch(i){let a=i.code??"unknown";return [`${e}(error: ${a})`]}n.sort((i,a)=>i.isDirectory()&&!a.isDirectory()?-1:!i.isDirectory()&&a.isDirectory()?1:i.name.localeCompare(a.name));let c=[];for(let i of n){let a=p.join(r,i.name);if(i.isDirectory())if(c.push(`${e}[DIR] ${i.name}/`),o<t){let l=await x(a,{currentDepth:o+1,maxDepth:t});c.push(...l);}else c.push(`${" ".repeat(o+1)}(max depth reached)`);else try{let l=await u.stat(a);c.push(`${e}[FILE] ${i.name} (${l.size} bytes)`);}catch{c.push(`${e}[FILE] ${i.name} (stat error)`);}}return c}async function h(r,s,o){try{let e=(await u.readFile(r,"utf-8")).split(`
|
|
2
|
+
`),n=p.relative(o,r);return e.flatMap((c,i)=>s.test(c)?[`${n}:${i+1}: ${c}`]:[])}catch{return []}}async function b(r,s,o,t=10,e=0){if(e>=t)return [];let n=[],c;try{c=await u.readdir(r,{withFileTypes:!0});}catch{return []}for(let i of c){let a=p.join(r,i.name);if(i.isDirectory()){if(!g.has(i.name)){let l=await b(a,s,o,t,e+1);n.push(...l);}}else {let l=await h(a,s,o);n.push(...l);}}return n}function j(r,s,o){let t=o?r:r.toLowerCase(),n=(o?s:s.toLowerCase()).replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*").replace(/\?/g,".");return new RegExp(`^${n}$`).test(t)}async function T(r,s,o,t,e,n=0){if(t.length>=e||n>10)return;let c;try{c=await u.readdir(r,{withFileTypes:!0});}catch{return}for(let i of c){if(t.length>=e)break;let a=p.join(r,i.name);i.isDirectory()?g.has(i.name)||await T(a,s,o,t,e,n+1):j(i.name,s,o)&&t.push(a);}}function L(r,s){let o=r.replace(/\\/g,"/"),e=s.replace(/\\/g,"/").replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*\//g,"\xA7\xA7\xA7").replace(/\*\*/g,"\xA7\xA7\xA7").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/§§§/g,".*");return new RegExp(`^${e}$`).test(o)}async function v(r,s,o,t,e,n=0){if(t.length>=e||n>15)return;let c;try{c=await u.readdir(r,{withFileTypes:!0});}catch{return}for(let i of c){if(t.length>=e)break;let a=p.join(r,i.name);if(i.isDirectory())g.has(i.name)||await v(a,s,o,t,e,n+1);else {let l=p.relative(o,a).replace(/\\/g,"/");L(l,s)&&t.push(a);}}}var P={description:"Reads and returns the content of a specified file. Use offset/limit to paginate large text files.",parameters:{type:"object",properties:{file_path:{type:"string",description:"Path to the file to read."},offset:{type:"integer",description:"Optional 0-based line number to start reading from."},limit:{type:"integer",description:"Optional maximum number of lines to read."}},required:["file_path"]},execute:async r=>{let s=r.file_path,o=r.offset,t=r.limit;if(!s.trim())throw new Error("The 'file_path' parameter must be non-empty.");let e=p.resolve(s),n=await u.readFile(e,"utf-8");if(o!==void 0||t!==void 0){let c=n.split(`
|
|
3
|
+
`),i=o??0,a=t!==void 0?i+t:c.length,l=c.slice(i,a),d=a<c.length,f=l.join(`
|
|
4
|
+
`);return d?`IMPORTANT: Content truncated. Showing lines ${i}-${a-1} of ${c.length}.
|
|
5
|
+
|
|
6
|
+
${f}`:f}return n}},I={description:"Creates a new file or overwrites an existing file with the provided content.",parameters:{type:"object",properties:{file_path:{type:"string",description:"Path to the file to create or overwrite."},content:{type:"string",description:"The content to write to the file."}},required:["file_path","content"]},execute:async r=>{let s=r.file_path,o=r.content;if(!s.trim())throw new Error("The 'file_path' parameter must be non-empty.");let t=p.resolve(s);await u.mkdir(p.dirname(t),{recursive:true});let e=false;try{await u.access(t),e=!0;}catch{}await u.writeFile(t,o,"utf-8");let n=Buffer.byteLength(o,"utf-8");return `${e?"Updated":"Created"} file: ${s} (${n} bytes)`}},B={description:"Replaces a range of lines in a file with new text. Line numbers are 1-based.",parameters:{type:"object",properties:{file_path:{type:"string",description:"Path to the file to modify."},start_line:{type:"integer",description:"Starting line number (1-based, inclusive)."},end_line:{type:"integer",description:"Ending line number (1-based, inclusive)."},new_text:{type:"string",description:"New text to insert in place of the specified lines."}},required:["file_path","start_line","end_line","new_text"]},execute:async r=>{let s=r.file_path,o=r.start_line,t=r.end_line,e=r.new_text;if(!s.trim())throw new Error("The 'file_path' parameter must be non-empty.");if(o>t)throw new Error(`start_line (${o}) must be <= end_line (${t}).`);let n=p.resolve(s),i=(await u.readFile(n,"utf-8")).split(`
|
|
7
|
+
`);if(o<1||o>i.length)throw new Error(`start_line (${o}) out of range. File has ${i.length} lines.`);if(t>i.length)throw new Error(`end_line (${t}) out of range. File has ${i.length} lines.`);let a=e.split(`
|
|
8
|
+
`);return i.splice(o-1,t-o+1,...a),await u.writeFile(n,i.join(`
|
|
9
|
+
`),"utf-8"),`Successfully replaced lines ${o}-${t} in ${s}`}},k={description:"Lists contents of a directory. Shows file sizes and marks directories with trailing slashes.",parameters:{type:"object",properties:{path:{type:"string",description:"Directory path to list (default: current directory)."},recursive:{type:"boolean",description:"List contents recursively (default: false)."}}},execute:async r=>{let s=r.path??".",o=r.recursive??false,t=p.resolve(s);if(!(await u.stat(t)).isDirectory())throw new Error(`Path is not a directory: ${s}`);let n=`Directory listing: ${s}
|
|
10
|
+
|
|
11
|
+
`;if(o){let c=await $(t,t);n+=c.join(`
|
|
12
|
+
`);}else {let c=await u.readdir(t,{withFileTypes:true}),i=[];for(let a of c)if(a.isDirectory())i.push(`${a.name}/`);else {let l=await u.stat(p.join(t,a.name));i.push(`${a.name} (${l.size} bytes)`);}n+=i.join(`
|
|
13
|
+
`);}return n||"Directory is empty"}},C={description:"Displays a directory tree with [DIR]/[FILE] labels up to max_depth levels.",parameters:{type:"object",properties:{path:{type:"string",description:"Directory to inspect (default: current directory)."},max_depth:{type:"integer",description:"Maximum depth to traverse (default: 3)."}}},execute:async r=>{let s=r.path??".",o=r.max_depth??3,t=p.resolve(s);if(!(await u.stat(t)).isDirectory())throw new Error(`Path is not a directory: ${s}`);let n=p.relative(process.cwd(),t),c=n===""?".":n,i=[`Tree for ${c} (max depth: ${o})`,`[DIR] ${c}/`],a=await x(t,{currentDepth:1,maxDepth:o});return i.push(...a),i.join(`
|
|
14
|
+
`)}},O={description:"Searches for a regex pattern in files. Returns matching lines with file paths and line numbers.",parameters:{type:"object",properties:{pattern:{type:"string",description:"Regular expression pattern to search for."},path:{type:"string",description:"File or directory path to search in (default: current directory)."},recursive:{type:"boolean",description:"Search recursively through subdirectories (default: true)."}},required:["pattern"]},execute:async r=>{let s=r.pattern,o=r.path??".",t=r.recursive??true;if(!s.trim())throw new Error("The 'pattern' parameter must be non-empty.");let e;try{e=new RegExp(s);}catch(m){throw new Error(`Invalid regular expression: ${m.message}`)}let n=p.resolve(o),c=await u.stat(n),i=c.isDirectory()?n:p.dirname(n),a=[];if(c.isDirectory())if(t)a=await b(n,e,i);else {let m=await u.readdir(n,{withFileTypes:true});for(let w of m)if(!w.isDirectory()){let _=await h(p.join(n,w.name),e,i);a.push(..._);}}else a=await h(n,e,i);if(a.length===0)return `No matches found for pattern: ${s}`;let l=100,d=a.slice(0,l),f=`Found ${a.length} match(es) for pattern: ${s}
|
|
15
|
+
|
|
16
|
+
${d.join(`
|
|
17
|
+
`)}`;return a.length>l&&(f+=`
|
|
18
|
+
|
|
19
|
+
... and ${a.length-l} more (output truncated)`),f}},q={description:"Searches for files by filename pattern. Supports * and ? wildcards.",parameters:{type:"object",properties:{pattern:{type:"string",description:"Filename pattern. Supports * and ? wildcards."},dir_path:{type:"string",description:"Directory to search in (default: current directory)."},case_sensitive:{type:"boolean",description:"Case-sensitive matching (default: false)."},max_results:{type:"integer",description:"Maximum results to return (default: 50)."}},required:["pattern"]},execute:async r=>{let s=r.pattern,o=r.dir_path??".",t=r.case_sensitive??false,e=r.max_results??50,n=p.resolve(o),c=[];if(await T(n,s,t,c,e),c.length===0)return `No files found matching pattern: ${s}
|
|
20
|
+
Searched in: ${n}`;let i=c.map((l,d)=>` ${d+1}. ${p.relative(process.cwd(),l)}`),a=c.length>=e?`
|
|
21
|
+
(Limited to ${e} results)`:"";return `Found ${c.length} file(s) matching "${s}":
|
|
22
|
+
${i.join(`
|
|
23
|
+
`)}${a}`}},A={description:'Finds files matching glob patterns (e.g., "**/*.ts", "src/**/*.yaml"). Returns file paths.',parameters:{type:"object",properties:{pattern:{type:"string",description:"Glob pattern to match files against."},dir_path:{type:"string",description:"Directory to search in (default: current directory)."},max_results:{type:"integer",description:"Maximum results to return (default: 100)."}},required:["pattern"]},execute:async r=>{let s=r.pattern,o=r.dir_path??".",t=r.max_results??100,e=p.resolve(o),n=[];if(await v(e,s,e,n,t),n.length===0)return `No files found matching pattern: ${s}
|
|
24
|
+
Searched in: ${e}`;let c=n.map((a,l)=>` ${l+1}. ${p.relative(process.cwd(),a)}`),i=n.length>=t?`
|
|
25
|
+
(Limited to ${t} results)`:"";return `Found ${n.length} file(s) matching "${s}":
|
|
26
|
+
${c.join(`
|
|
27
|
+
`)}${i}`}},N={description:"Executes a shell command and returns its output (stdout and stderr). Use with caution.",parameters:{type:"object",properties:{command:{type:"string",description:"The shell command to execute."},timeout_seconds:{type:"integer",description:"Maximum execution time in seconds (default: 30)."}},required:["command"]},execute:async r=>{let s=r.command,o=r.timeout_seconds??30;if(!s.trim())throw new Error("The 'command' parameter must be non-empty.");try{let{stdout:t,stderr:e}=await F(s,{timeout:o*1e3,maxBuffer:10485760,cwd:process.cwd()}),n="";return t&&(n+=`STDOUT:
|
|
28
|
+
${t}`),e&&(n+=(t?`
|
|
29
|
+
|
|
30
|
+
`:"")+`STDERR:
|
|
31
|
+
${e}`),n||"Command executed successfully (no output)"}catch(t){let e=t;if(e.killed&&e.signal==="SIGTERM")throw new Error(`Command timed out after ${o} seconds`);let n=`Command failed: ${s}`;throw e.stdout&&(n+=`
|
|
32
|
+
STDOUT:
|
|
33
|
+
${e.stdout}`),e.stderr&&(n+=`
|
|
34
|
+
STDERR:
|
|
35
|
+
${e.stderr}`),e.code!==void 0&&(n+=`
|
|
36
|
+
Exit code: ${e.code}`),new Error(n)}}},y={read_file:P,write_file:I,replace:B,ls:k,tree:C,grep:O,find:q,glob:A,run_shell_command:N};function K(r){let s=r.config;if(!s)return;let o=s.agents??[],t=new Set;for(let e of o){if(!(Array.isArray(e.provider)?e.provider:[e.provider]).some(a=>typeof a=="string"&&a.startsWith("api/")))continue;let i=e.options;if(Array.isArray(i?.query?.tools))for(let a of i.query.tools)t.add(a);if(Array.isArray(i?.execute?.tools))for(let a of i.execute.tools)t.add(a);}for(let e of t){let n=y[e];n&&r.registerTool(e,n);}}export{y as BUILTIN_TOOL_REGISTRY,K as registerBuiltinTools};
|
|
@@ -1,31 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypedEventEmitter — typed wrapper around Node's EventEmitter.
|
|
3
|
-
*
|
|
4
|
-
* Design:
|
|
5
|
-
* - `on` / `once` are public (callers subscribe)
|
|
6
|
-
* - `emit` is protected (only subclasses like Crewx can emit)
|
|
7
|
-
* - Async listeners are supported (fire-and-forget, errors isolated)
|
|
8
|
-
* - Returns an UnsubscribeFn from on/once for easy cleanup
|
|
9
|
-
*/
|
|
10
1
|
import type { CrewxEventName, CrewxEventPayload, UnsubscribeFn } from './types';
|
|
11
2
|
export declare class TypedEventEmitter {
|
|
12
3
|
private readonly _emitter;
|
|
13
|
-
/**
|
|
14
|
-
* Subscribe to an event. Returns an unsubscribe function.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* const unsub = crewx.on('task:start', (e) => console.log(e.agentRef));
|
|
18
|
-
* // later:
|
|
19
|
-
* unsub();
|
|
20
|
-
*/
|
|
21
4
|
on<K extends CrewxEventName>(event: K, listener: (payload: CrewxEventPayload<K>) => void | Promise<void>): UnsubscribeFn;
|
|
22
|
-
/**
|
|
23
|
-
* Subscribe to an event exactly once.
|
|
24
|
-
*/
|
|
25
5
|
once<K extends CrewxEventName>(event: K, listener: (payload: CrewxEventPayload<K>) => void | Promise<void>): UnsubscribeFn;
|
|
26
|
-
/**
|
|
27
|
-
* Emit an event with payload. Only accessible to subclasses.
|
|
28
|
-
*/
|
|
29
6
|
protected emit<K extends CrewxEventName>(event: K, payload: CrewxEventPayload<K>): void;
|
|
30
7
|
}
|
|
31
|
-
//# sourceMappingURL=TypedEventEmitter.d.ts.map
|
package/dist/events/types.d.ts
CHANGED
|
@@ -1,83 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Event types for the CrewX SDK event system.
|
|
3
|
-
*
|
|
4
|
-
* SDK emits events; callers (CLI, users) subscribe to persist or react.
|
|
5
|
-
* No DB dependencies in the SDK — storage is the caller's responsibility.
|
|
6
|
-
*/
|
|
7
1
|
import type { Platform } from '../conversation/types';
|
|
8
|
-
/** Base fields present on every event. */
|
|
9
2
|
export interface BaseEvent {
|
|
10
|
-
/** Unique trace ID for correlating start/end events. Format: tsk_XXXXXXXX */
|
|
11
3
|
traceId: string;
|
|
12
|
-
/** Event timestamp */
|
|
13
4
|
timestamp: Date;
|
|
14
5
|
}
|
|
15
|
-
/** Emitted when a query() or execute() call begins. */
|
|
16
6
|
export interface TaskStartEvent extends BaseEvent {
|
|
17
|
-
/** Agent reference (e.g. "@claude", "claude") */
|
|
18
7
|
agentRef: string;
|
|
19
|
-
/** The message/prompt being sent */
|
|
20
8
|
message: string;
|
|
21
|
-
/** "query" or "execute" */
|
|
22
9
|
mode: 'query' | 'execute';
|
|
23
|
-
/** PID of the spawned child process (undefined for non-process providers) */
|
|
24
10
|
pid?: number;
|
|
25
|
-
/** Effective model used (e.g. "claude-sonnet-4-6") */
|
|
26
11
|
model?: string;
|
|
27
|
-
/** Provider string (e.g. "cli/claude") */
|
|
28
12
|
provider?: string;
|
|
29
|
-
/** Full CLI command spawned (e.g. "claude -p ... --output-format stream-json") */
|
|
30
13
|
codingAgentCommand?: string;
|
|
31
|
-
/** Full rendered agent system prompt (Handlebars-rendered) */
|
|
32
14
|
renderedPrompt?: string;
|
|
33
|
-
/** Extra metadata (e.g. { provider: "cli/claude" }) */
|
|
34
15
|
metadata?: Record<string, unknown>;
|
|
35
|
-
/** Conversation thread ID */
|
|
36
16
|
threadId?: string;
|
|
37
|
-
/** Platform origin. Defaults to 'cli'. */
|
|
38
17
|
platform?: Platform;
|
|
39
|
-
/** Workspace ID (SHA-256 hash of normalized cwd). Single source of truth from Crewx instance. */
|
|
40
18
|
workspaceId?: string;
|
|
41
|
-
/** Human-readable workspace name (basename of cwd). */
|
|
42
19
|
workspaceName?: string;
|
|
43
20
|
}
|
|
44
|
-
/** Emitted when a query() or execute() call completes (success or failure). */
|
|
45
21
|
export interface TaskEndEvent extends BaseEvent {
|
|
46
|
-
/** Agent reference */
|
|
47
22
|
agentRef: string;
|
|
48
|
-
/** "query" or "execute" */
|
|
49
23
|
mode: 'query' | 'execute';
|
|
50
|
-
/** Result data (on success) */
|
|
51
24
|
result?: string;
|
|
52
|
-
/** Elapsed time in milliseconds */
|
|
53
25
|
durationMs: number;
|
|
54
|
-
/** Error info (on failure) */
|
|
55
26
|
error?: {
|
|
56
27
|
code: string;
|
|
57
28
|
message: string;
|
|
58
29
|
};
|
|
59
|
-
/** Provider process exit code (0 = success) */
|
|
60
30
|
exitCode?: number;
|
|
61
|
-
/** Total input tokens consumed */
|
|
62
31
|
inputTokens?: number;
|
|
63
|
-
/** Total output tokens consumed */
|
|
64
32
|
outputTokens?: number;
|
|
65
|
-
/** Cache-read input tokens */
|
|
66
33
|
cachedInputTokens?: number;
|
|
67
|
-
/** Total cost in USD */
|
|
68
34
|
costUsd?: number;
|
|
69
|
-
/** Actual model used (may differ from agent config when resolved at runtime) */
|
|
70
35
|
model?: string;
|
|
71
|
-
/** Extra metadata propagated from QueryOptions/ExecuteOptions.metadata (e.g. workflow info) */
|
|
72
36
|
metadata?: Record<string, unknown>;
|
|
73
37
|
}
|
|
74
|
-
/** Emitted for each output line from the provider process. */
|
|
75
38
|
export interface TaskOutputEvent extends BaseEvent {
|
|
76
|
-
/** Agent reference */
|
|
77
39
|
agentRef: string;
|
|
78
|
-
/** One line of raw output */
|
|
79
40
|
output: string;
|
|
80
|
-
/** Output stream origin */
|
|
81
41
|
level?: 'stdout' | 'stderr' | 'info';
|
|
82
42
|
}
|
|
83
43
|
export interface ToolBeforeEvent extends BaseEvent {
|
|
@@ -122,7 +82,6 @@ export interface AdapterMessageEvent {
|
|
|
122
82
|
threadId: string;
|
|
123
83
|
timestamp: Date;
|
|
124
84
|
}
|
|
125
|
-
/** All events emitted by the Crewx SDK. */
|
|
126
85
|
export interface CrewxEvents {
|
|
127
86
|
'task:start': TaskStartEvent;
|
|
128
87
|
'task:end': TaskEndEvent;
|
|
@@ -134,6 +93,4 @@ export interface CrewxEvents {
|
|
|
134
93
|
}
|
|
135
94
|
export type CrewxEventName = keyof CrewxEvents;
|
|
136
95
|
export type CrewxEventPayload<K extends CrewxEventName> = CrewxEvents[K];
|
|
137
|
-
/** Call to remove a specific event listener. */
|
|
138
96
|
export type UnsubscribeFn = () => void;
|
|
139
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,34 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser-safe Crewx facade.
|
|
3
|
-
*
|
|
4
|
-
* Stripped of all Node.js dependencies (path, fs, child_process, crypto, events).
|
|
5
|
-
* Supports: fromConfig(), query(), execute(), registerTool(), agents, tools.
|
|
6
|
-
*
|
|
7
|
-
* Built-in providers (e.g. api/webllm) are auto-initialised when detected
|
|
8
|
-
* in the agents list — no manual registerProviderFactory required.
|
|
9
|
-
*/
|
|
10
1
|
import type { AgentConfig, CrewxProjectConfig, QueryOptions as BaseQueryOptions, QueryResult, ExecuteOptions, ExecuteResult } from '../types/index.js';
|
|
11
|
-
/**
|
|
12
|
-
* Definition for a custom tool that can be registered via crewx.registerTool().
|
|
13
|
-
*/
|
|
14
2
|
export interface ToolDefinition {
|
|
15
3
|
name: string;
|
|
16
4
|
description: string;
|
|
17
5
|
parameters?: Record<string, unknown>;
|
|
18
6
|
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
19
7
|
}
|
|
20
|
-
/** Extended query options with browser streaming callback. */
|
|
21
8
|
export interface BrowserQueryOptions extends BaseQueryOptions {
|
|
22
9
|
onOutput?: (partial: string) => void;
|
|
23
10
|
}
|
|
24
|
-
/** Options for Crewx.fromConfig() in the browser environment. */
|
|
25
11
|
export interface BrowserFromConfigOptions {
|
|
26
|
-
/** Progress callback for model loading (web-llm). */
|
|
27
12
|
onProgress?: (report: {
|
|
28
13
|
progress?: number;
|
|
29
14
|
text?: string;
|
|
30
15
|
}) => void;
|
|
31
|
-
/** API key for OpenRouter provider. Required when any agent uses api/openrouter. */
|
|
32
16
|
openrouterApiKey?: string;
|
|
33
17
|
}
|
|
34
18
|
export declare class Crewx {
|
|
@@ -37,37 +21,13 @@ export declare class Crewx {
|
|
|
37
21
|
private readonly _tools;
|
|
38
22
|
private readonly _apiProviders;
|
|
39
23
|
private constructor();
|
|
40
|
-
/**
|
|
41
|
-
* Create a Crewx instance from an already-parsed config object.
|
|
42
|
-
*
|
|
43
|
-
* Built-in browser providers (api/webllm, api/openrouter) are auto-initialised
|
|
44
|
-
* when detected in the agents list — no manual registerProviderFactory required.
|
|
45
|
-
*/
|
|
46
24
|
static fromConfig(config: CrewxProjectConfig, options?: BrowserFromConfigOptions): Promise<Crewx>;
|
|
47
|
-
/**
|
|
48
|
-
* Load web-llm from CDN, create the inference engine, and store
|
|
49
|
-
* the provider runtime. Called automatically by fromConfig().
|
|
50
|
-
*/
|
|
51
25
|
private _initWebLLM;
|
|
52
|
-
/**
|
|
53
|
-
* Initialise the OpenRouter API provider.
|
|
54
|
-
* Uses fetch + SSE streaming against the OpenAI-compatible endpoint.
|
|
55
|
-
*/
|
|
56
26
|
private _initOpenRouter;
|
|
57
27
|
get agents(): ReadonlyMap<string, AgentConfig>;
|
|
58
28
|
get config(): CrewxProjectConfig | undefined;
|
|
59
29
|
get tools(): ReadonlyMap<string, ToolDefinition>;
|
|
60
30
|
registerTool(name: string, definition: Omit<ToolDefinition, 'name'>): void;
|
|
61
|
-
/**
|
|
62
|
-
* Query an agent with a message.
|
|
63
|
-
* Browser version — delegates directly to the registered provider factory.
|
|
64
|
-
* Passes onOutput through for streaming support.
|
|
65
|
-
*/
|
|
66
31
|
query(agentRef: string, message: string, options?: BrowserQueryOptions): Promise<QueryResult>;
|
|
67
|
-
/**
|
|
68
|
-
* Execute a task with an agent.
|
|
69
|
-
* Browser version — same delegation pattern as query().
|
|
70
|
-
*/
|
|
71
32
|
execute(agentRef: string, message: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
72
33
|
}
|
|
73
|
-
//# sourceMappingURL=Crewx.browser.d.ts.map
|
package/dist/facade/Crewx.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Crewx facade — main entry point for the CrewX SDK.
|
|
3
|
-
* Provides loadYaml(), fromConfig(), query(), execute(), renderAgentPromptFull(),
|
|
4
|
-
* and registerLayout() methods.
|
|
5
|
-
*/
|
|
6
1
|
import { TypedEventEmitter } from '../events/TypedEventEmitter';
|
|
7
2
|
import type { CrewxPlugin } from '../plugin';
|
|
8
3
|
import type { IFsAdapter } from '../platform/IFsAdapter';
|
|
@@ -13,33 +8,18 @@ import type { CustomLayoutDefinition } from '../layout/types';
|
|
|
13
8
|
import type { TemplateMessage } from '../conversation/types';
|
|
14
9
|
import type { HandlerOptions, CrewxHandler } from '../server/handler';
|
|
15
10
|
import type { RemoteProviderConfig } from '../remote/types.js';
|
|
16
|
-
/**
|
|
17
|
-
* Definition for a custom tool that can be registered via crewx.registerTool().
|
|
18
|
-
* Tools are made available in the agent prompt context for browser/API environments.
|
|
19
|
-
*/
|
|
20
11
|
export interface ToolDefinition {
|
|
21
|
-
/** Tool name (unique identifier). */
|
|
22
12
|
name: string;
|
|
23
|
-
/** Human-readable description of what the tool does. */
|
|
24
13
|
description: string;
|
|
25
|
-
/** JSON Schema for tool parameters (optional). */
|
|
26
14
|
parameters?: Record<string, unknown>;
|
|
27
|
-
/** Tool execution function. Omit for client-side tools (Vercel AI SDK client tools). */
|
|
28
15
|
execute?: (args: Record<string, unknown>) => Promise<unknown>;
|
|
29
16
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Layout specification for renderAgentPromptFull options.
|
|
32
|
-
* Matches the crewx.yaml inline.layout schema.
|
|
33
|
-
*/
|
|
34
17
|
export type LayoutSpec = string | {
|
|
35
18
|
id: string;
|
|
36
19
|
props?: Record<string, any>;
|
|
37
20
|
} | {
|
|
38
21
|
template: string;
|
|
39
22
|
};
|
|
40
|
-
/**
|
|
41
|
-
* Skill entry for available_skills rendering in agent prompts.
|
|
42
|
-
*/
|
|
43
23
|
export interface SkillEntry {
|
|
44
24
|
metadata: {
|
|
45
25
|
name: string;
|
|
@@ -48,25 +28,16 @@ export interface SkillEntry {
|
|
|
48
28
|
};
|
|
49
29
|
filePath: string;
|
|
50
30
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Options for renderAgentPromptFull().
|
|
53
|
-
*/
|
|
54
31
|
export interface RenderAgentPromptOptions {
|
|
55
|
-
/** Override layout resolution. Priority: options.layout > agent.inline.layout > project default > SDK default. */
|
|
56
32
|
layout?: LayoutSpec;
|
|
57
|
-
/** Override session info (default: { mode: 'query', platform: 'cli' }). */
|
|
58
33
|
session?: {
|
|
59
34
|
mode?: string;
|
|
60
35
|
platform?: string;
|
|
61
36
|
options?: string[];
|
|
62
37
|
};
|
|
63
|
-
/** Override env (default: process.env). */
|
|
64
38
|
env?: Record<string, string>;
|
|
65
|
-
/** Override vars (e.g. security_key). Default: auto-generated. */
|
|
66
39
|
vars?: Record<string, unknown>;
|
|
67
|
-
/** Skills to inject as available_skills context. Default: []. */
|
|
68
40
|
skills?: SkillEntry[];
|
|
69
|
-
/** Conversation history messages for layout rendering (WI-CONV-002). Caller-provided takes priority over auto-fetch. */
|
|
70
41
|
messages?: TemplateMessage[];
|
|
71
42
|
}
|
|
72
43
|
export declare class Crewx extends TypedEventEmitter {
|
|
@@ -83,185 +54,51 @@ export declare class Crewx extends TypedEventEmitter {
|
|
|
83
54
|
private readonly _tools;
|
|
84
55
|
private readonly _activeAdapters;
|
|
85
56
|
private readonly _pendingThreads;
|
|
86
|
-
/**
|
|
87
|
-
* Bootstrap factory for target Crewx instances when delegating file:// remote agents.
|
|
88
|
-
* Consumers (CLI / server / Slack) provide their own bootstrap wrapper so that the
|
|
89
|
-
* target inherits the same plugin/environment setup as the caller.
|
|
90
|
-
*/
|
|
91
57
|
private readonly _remoteFactory?;
|
|
92
|
-
/** Lazily-created target Crewx instances, keyed by absolute configPath. */
|
|
93
58
|
private readonly _remoteTargets;
|
|
94
59
|
private constructor();
|
|
95
|
-
/**
|
|
96
|
-
* If `agentRef` resolves to a `remote/*` provider backed by `file://`, return
|
|
97
|
-
* the target Crewx (lazily bootstrapped) together with the agent ref to use
|
|
98
|
-
* inside the target. Returns null for local agents or non-file remotes.
|
|
99
|
-
*
|
|
100
|
-
* The caller's Crewx.query/execute delegates entirely to the returned target
|
|
101
|
-
* (including task:start/end emit, renderContext, plugins) so execution
|
|
102
|
-
* semantics exactly match running `crewx q` inside the target workspace.
|
|
103
|
-
*/
|
|
104
60
|
private resolveFileRemoteTarget;
|
|
105
|
-
/**
|
|
106
|
-
* Load crewx.yaml from the given file path and create a Crewx instance.
|
|
107
|
-
*/
|
|
108
61
|
static loadYaml(path: string, options?: CrewxOptions, fsAdapter?: IFsAdapter): Promise<Crewx>;
|
|
109
|
-
/**
|
|
110
|
-
* Create a Crewx instance from an already-parsed config object.
|
|
111
|
-
*/
|
|
112
62
|
static fromConfig(config: CrewxProjectConfig, options?: CrewxOptions, projectRoot?: string, fsAdapter?: IFsAdapter): Promise<Crewx>;
|
|
113
|
-
/** All loaded agents, keyed by agent id. */
|
|
114
63
|
get agents(): ReadonlyMap<string, AgentConfig>;
|
|
115
|
-
/** The raw project config (includes providers, settings, etc.). */
|
|
116
64
|
get config(): CrewxProjectConfig | undefined;
|
|
117
|
-
/** All registered plugins. */
|
|
118
65
|
get plugins(): readonly CrewxPlugin[];
|
|
119
|
-
/** All registered custom tools. */
|
|
120
66
|
get tools(): ReadonlyMap<string, ToolDefinition>;
|
|
121
|
-
/** Workspace ID (SHA-256 hash). Single source of truth for all plugins. */
|
|
122
67
|
get workspaceId(): string;
|
|
123
|
-
/** Human-readable workspace name (basename of cwd). */
|
|
124
68
|
get workspaceName(): string;
|
|
125
|
-
/**
|
|
126
|
-
* Return an agent config by ref (with or without leading '@').
|
|
127
|
-
* Returns undefined if the agent is not found.
|
|
128
|
-
*/
|
|
129
69
|
getAgent(agentRef: string): AgentConfig | undefined;
|
|
130
|
-
/**
|
|
131
|
-
* Return a remote provider config by provider ID from the crewx.yaml `providers:` section.
|
|
132
|
-
* Returns undefined if not found or if config has no providers.
|
|
133
|
-
*/
|
|
134
70
|
getRemoteProviderConfig(providerId: string): RemoteProviderConfig | undefined;
|
|
135
71
|
private computeTaskLogPath;
|
|
136
|
-
/**
|
|
137
|
-
* Register a custom tool for use in agent prompts.
|
|
138
|
-
*
|
|
139
|
-
* Registered tools are included in the `tools` context of renderAgentPromptFull(),
|
|
140
|
-
* and can be invoked programmatically (e.g. in browser environments with API providers).
|
|
141
|
-
*
|
|
142
|
-
* @param name - Unique tool name (overwrites if already registered)
|
|
143
|
-
* @param definition - Tool definition with description, parameters, and execute function
|
|
144
|
-
*/
|
|
145
72
|
registerTool(name: string, definition: Omit<ToolDefinition, 'name'>): void;
|
|
146
|
-
/**
|
|
147
|
-
* Register a plugin and immediately call attach().
|
|
148
|
-
* Same instance registered twice is silently ignored (by reference).
|
|
149
|
-
*/
|
|
150
73
|
use(plugin: CrewxPlugin): Promise<void>;
|
|
151
|
-
/**
|
|
152
|
-
* Create a Web Standard MCP HTTP handler for exposing agents over the network.
|
|
153
|
-
*
|
|
154
|
-
* @param options - Handler config. `agents` list is required for security.
|
|
155
|
-
* @returns `(req: Request) => Promise<Response>` handler
|
|
156
|
-
*/
|
|
157
74
|
handler(options: HandlerOptions): CrewxHandler;
|
|
158
|
-
/**
|
|
159
|
-
* Register a channel adapter and start it.
|
|
160
|
-
*/
|
|
161
75
|
registerChannelAdapter<TConfig = unknown>(reg: ChannelAdapterRegistration<TConfig>): Promise<void>;
|
|
162
|
-
/**
|
|
163
|
-
* Unregister and stop a channel adapter by instanceId.
|
|
164
|
-
*/
|
|
165
76
|
unregisterChannelAdapter(instanceId: string): Promise<void>;
|
|
166
|
-
/**
|
|
167
|
-
* Stop all registered adapters with a timeout.
|
|
168
|
-
*/
|
|
169
77
|
stopAllAdapters(opts?: {
|
|
170
78
|
timeoutMs?: number;
|
|
171
79
|
}): Promise<void>;
|
|
172
|
-
/**
|
|
173
|
-
* Detach all plugins in LIFO order and release resources.
|
|
174
|
-
* Call before process exit for clean shutdown.
|
|
175
|
-
*/
|
|
176
80
|
close(): Promise<void>;
|
|
177
|
-
/**
|
|
178
|
-
* Filter agents by role, team, and/or provider.
|
|
179
|
-
*/
|
|
180
81
|
filterAgents(filters: {
|
|
181
82
|
role?: string;
|
|
182
83
|
team?: string;
|
|
183
84
|
provider?: string;
|
|
184
85
|
}): AgentConfig[];
|
|
185
|
-
/**
|
|
186
|
-
* Return the raw system prompt for the given agent (no template expansion, no layout).
|
|
187
|
-
* @throws AgentNotFoundError if agentId is not found
|
|
188
|
-
*/
|
|
189
86
|
renderAgentPrompt(agentId: string): string;
|
|
190
|
-
/**
|
|
191
|
-
* Render a Handlebars template string with the given context.
|
|
192
|
-
* Documents from crewx.yaml are automatically merged into context.documents.
|
|
193
|
-
*/
|
|
194
87
|
renderPrompt(template: string, context?: TemplateContext): Promise<string>;
|
|
195
|
-
/**
|
|
196
|
-
* Register a custom layout template at runtime.
|
|
197
|
-
*
|
|
198
|
-
* @param name - Layout identifier (used as-is, no forced namespace)
|
|
199
|
-
* @param template - Handlebars template string or CustomLayoutDefinition
|
|
200
|
-
*/
|
|
201
88
|
registerLayout(name: string, template: string | CustomLayoutDefinition): void;
|
|
202
|
-
/**
|
|
203
|
-
* Render the full agent prompt using the layout system.
|
|
204
|
-
*
|
|
205
|
-
* Resolution priority (first match wins):
|
|
206
|
-
* 1. options.layout (call-site override)
|
|
207
|
-
* 2. agent.inline.layout (agent YAML definition)
|
|
208
|
-
* 3. config.layouts.default (project-level default)
|
|
209
|
-
* 4. SDK built-in default (crewx/default)
|
|
210
|
-
*
|
|
211
|
-
* @param agentId - Agent ID (with or without leading '@')
|
|
212
|
-
* @param options - Optional layout/session/env/vars overrides
|
|
213
|
-
* @throws AgentNotFoundError if agentId is not found
|
|
214
|
-
*/
|
|
215
89
|
renderAgentPromptFull(agentId: string, options?: RenderAgentPromptOptions): Promise<string>;
|
|
216
|
-
/**
|
|
217
|
-
* Filter tools by allowed names from agent options (query/execute mode).
|
|
218
|
-
* If allowedNames is undefined, return all registered tools.
|
|
219
|
-
*/
|
|
220
90
|
private _filterToolsByMode;
|
|
221
|
-
/**
|
|
222
|
-
* Resolve layout spec following the priority order.
|
|
223
|
-
*/
|
|
224
91
|
private _resolveLayoutSpec;
|
|
225
|
-
/** Extract the layout ID string from a LayoutSpec. */
|
|
226
92
|
private _extractLayoutId;
|
|
227
|
-
/** Extract layout props overrides from agent inline.layout and call-site options. */
|
|
228
93
|
private _extractLayoutProps;
|
|
229
|
-
/**
|
|
230
|
-
* Get the ConversationPlugin's provider for history auto-fetch (WI-CONV-002).
|
|
231
|
-
* Returns undefined if no ConversationPlugin is registered.
|
|
232
|
-
*/
|
|
233
94
|
private _getConversationProvider;
|
|
234
|
-
/**
|
|
235
|
-
* Auto-fetch conversation history and convert to TemplateMessage[] (WI-CONV-002).
|
|
236
|
-
* Returns undefined if no threadId, no provider, or fetch fails.
|
|
237
|
-
*/
|
|
238
95
|
private _fetchHistoryMessages;
|
|
239
96
|
private emitToolEvents;
|
|
240
97
|
private tryParseJson;
|
|
241
|
-
/**
|
|
242
|
-
* Query an agent with a message.
|
|
243
|
-
*
|
|
244
|
-
* Emits task:start (with child pid when available) then task:output per
|
|
245
|
-
* stdout/stderr line, then task:end on completion or error.
|
|
246
|
-
*/
|
|
247
98
|
query(agentRef: string, message: string, options?: QueryOptions): Promise<QueryResult>;
|
|
248
|
-
/**
|
|
249
|
-
* Continue a conversation after providing client-side tool results.
|
|
250
|
-
*
|
|
251
|
-
* Called when a previous query() returned status: 'requires_action'.
|
|
252
|
-
* Feeds the tool result back to the agent and resumes generation.
|
|
253
|
-
* May return 'requires_action' again if the agent calls another client tool.
|
|
254
|
-
*/
|
|
255
99
|
continueQuery(threadId: string, toolResults: Array<{
|
|
256
100
|
toolCallId: string;
|
|
257
101
|
result: unknown;
|
|
258
102
|
}>): Promise<QueryResult>;
|
|
259
|
-
/**
|
|
260
|
-
* Execute a task with an agent.
|
|
261
|
-
*
|
|
262
|
-
* Emits task:start (with child pid when available) then task:output per
|
|
263
|
-
* stdout/stderr line, then task:end on completion or error.
|
|
264
|
-
*/
|
|
265
103
|
execute(agentRef: string, message: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
266
104
|
}
|
|
267
|
-
//# sourceMappingURL=Crewx.d.ts.map
|
package/dist/hooks/define.d.ts
CHANGED
package/dist/hooks/dispatch.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security notes:
|
|
3
|
-
*
|
|
4
|
-
* (M1) Codex `systemMessage` is merged into the agent's system prompt directly.
|
|
5
|
-
* Guide messages MUST NOT contain dynamic external input (tool_input,
|
|
6
|
-
* external API results, etc.) to prevent prompt injection via hook inject.
|
|
7
|
-
*
|
|
8
|
-
* Provider matching: When `provider` is not specified in a hook definition,
|
|
9
|
-
* it applies to ALL providers (§4.1.1 2-Layer Selector design).
|
|
10
|
-
* This is intentional — allows catch-all safety rules.
|
|
11
|
-
*/
|
|
12
1
|
import type { HookContext } from '../hooks/types';
|
|
13
2
|
import type { HookPlugin } from '../hooks/plugin';
|
|
14
3
|
export interface ClaudeHookInput {
|
|
@@ -58,4 +47,3 @@ export declare function formatInjectOutput(provider: Provider, hookEventName: st
|
|
|
58
47
|
export declare function formatDenyOutput(_provider: Provider, hookEventName: string, reason: string): ProviderHookOutput;
|
|
59
48
|
export declare function buildHookContext(input: ClaudeHookInput, cwd: string, provider?: string): HookContext;
|
|
60
49
|
export declare function evaluateHook(plugin: HookPlugin, input: ClaudeHookInput, cwd: string, provider?: string): Promise<HookDispatchResult>;
|
|
61
|
-
//# sourceMappingURL=dispatch.d.ts.map
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -10,4 +10,3 @@ export { Tools } from './types';
|
|
|
10
10
|
export type { ObserverContext, ObserverResult, ObserverEvent, HookContext, HookResult, HookEvent, ToolName, ToolInputPatch, Capability, } from './types';
|
|
11
11
|
export { evaluateHook, sanitizeDenyReason, sanitizeInjectMessage, isPathSafe, buildHookContext, formatInjectOutput, formatDenyOutput, } from './dispatch';
|
|
12
12
|
export type { ClaudeHookInput, ClaudeHookOutput, CodexHookOutput, ProviderHookOutput, Provider, HookDispatchResult, } from './dispatch';
|
|
13
|
-
//# sourceMappingURL=index.d.ts.map
|