@xopcai/xopc 0.0.85 → 0.0.86
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/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agents-D3_-kNlZ.js → agents-mS3_HpRI.js} +10 -10
- package/dist/gateway/static/root/assets/{apps-page-D7v7649T.js → apps-page-DrfytjOb.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-nCaMb0a7.js → channels-settings-BG6b9KrW.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-C1gZBcJV.js → channels-status-swr-Bs5kMCMI.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-CoYK0hlm.js → cron-api-BuVcZ5zR.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-DeGo-Vjc.js → cron-page-BMrloeFH.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-DaK4dsss.js → dist-CKU1OOTf.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BZngZWbO.js → extension-debug-page-BdW_46sN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-D6JSyV27.js → extension-page-DW47KI82.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-B-W4x2xP.js +1 -0
- package/dist/gateway/static/root/assets/{field-primitives-Zzl22MvN.js → field-primitives-DPG-oJmx.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BtIcpG0O.js → heartbeat-config-api-C8dNts9i.js} +1 -1
- package/dist/gateway/static/root/assets/{index-D4vM3-P7.js → index-BmVYculr.js} +20 -20
- package/dist/gateway/static/root/assets/{logs-page-_d4UJ-qQ.js → logs-page-sTsVWz0X.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-5N4aF2Wk.js → sessions-page-FaG_Vlkb.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-DuvRQW--.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-Bet1OerL.js +3 -0
- package/dist/gateway/static/root/assets/{share-preview-page-D4EG_vM1.js → share-preview-page-BtG2kLDh.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-sPAXhh8w.js → skills-page-DhUO235y.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-CYO9eTCM.js → utils-BY7bU1DT.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-Ds51havm.js → voice-api-key-field-CGEydndO.js} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/tools/workflow-tool.js +3 -3
- package/dist/src/agent/tools/workflow-tool.js.map +1 -1
- package/dist/src/agent/workflow/builtins/audit-repo.d.ts +5 -1
- package/dist/src/agent/workflow/builtins/audit-repo.js +52 -11
- package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -1
- package/dist/src/agent/workflow/builtins/debug-incident.d.ts +13 -0
- package/dist/src/agent/workflow/builtins/debug-incident.js +155 -0
- package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -0
- package/dist/src/agent/workflow/builtins/index.d.ts +3 -1
- package/dist/src/agent/workflow/builtins/index.js +11 -1
- package/dist/src/agent/workflow/builtins/index.js.map +1 -1
- package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +6 -1
- package/dist/src/agent/workflow/builtins/multi-perspective-review.js +66 -30
- package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -1
- package/dist/src/agent/workflow/builtins/pr-review.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/pr-review.js +156 -0
- package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -0
- package/dist/src/agent/workflow/builtins/research.d.ts +5 -1
- package/dist/src/agent/workflow/builtins/research.js +37 -6
- package/dist/src/agent/workflow/builtins/research.js.map +1 -1
- package/dist/src/agent/workflow/catalog.d.ts +5 -0
- package/dist/src/agent/workflow/catalog.js +6 -2
- package/dist/src/agent/workflow/catalog.js.map +1 -1
- package/dist/src/agent/workflow/index.d.ts +1 -1
- package/dist/src/agent/workflow/parser.js +9 -0
- package/dist/src/agent/workflow/parser.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +8 -0
- package/dist/src/chat-commands/builtins/workflow.js +7 -2
- package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-8PZcmWI7.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-D_tgb8r2.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-C18xBt4X.js +0 -3
|
@@ -8,4 +8,4 @@ export { emptySnapshotFor, runWorkflow, type RunWorkflowDeps, } from './runtime.
|
|
|
8
8
|
export { createWorkflowSnapshot, previewValue, recomputeCounts, renderWorkflowText, type RenderOptions, } from './snapshot.js';
|
|
9
9
|
export { createStructuredOutputTool, STRUCTURED_OUTPUT_TOOL_NAME, type CreateStructuredOutputToolOptions, type StructuredOutputCapture, } from './structured-output-tool.js';
|
|
10
10
|
export { DelegateSubagentRunner, type DelegateSubagentRunnerDeps, } from './subagent-runner.js';
|
|
11
|
-
export type { AgentScriptOptions, JsonSchema, SubagentRunner, SubagentRunOptions, WorkflowAgentSnapshot, WorkflowAgentStatus, WorkflowMeta, WorkflowMetaPhase, WorkflowRunOptions, WorkflowRunResult, WorkflowSnapshot, } from './types.js';
|
|
11
|
+
export type { AgentScriptOptions, JsonSchema, SubagentRunner, SubagentRunOptions, WorkflowAgentSnapshot, WorkflowAgentStatus, WorkflowMeta, WorkflowMetaEstimatedAgents, WorkflowMetaPhase, WorkflowRunOptions, WorkflowRunResult, WorkflowSnapshot, } from './types.js';
|
|
@@ -130,6 +130,15 @@ function validateMeta(meta) {
|
|
|
130
130
|
if (!Array.isArray(value.phases)) throw new Error("meta.phases must be an array");
|
|
131
131
|
for (const phase of value.phases) if (!phase || typeof phase !== "object" || typeof phase.title !== "string") throw new Error("each meta phase must have a title string");
|
|
132
132
|
}
|
|
133
|
+
if (value.tags !== void 0) {
|
|
134
|
+
if (!Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== "string" || !tag.trim())) throw new Error("meta.tags must be an array of non-empty strings");
|
|
135
|
+
}
|
|
136
|
+
if (value.estimatedAgents !== void 0) {
|
|
137
|
+
const est = value.estimatedAgents;
|
|
138
|
+
if (!est || typeof est !== "object") throw new Error("meta.estimatedAgents must be an object");
|
|
139
|
+
if (typeof est.min !== "number" || typeof est.max !== "number" || !Number.isFinite(est.min) || !Number.isFinite(est.max)) throw new Error("meta.estimatedAgents.min and .max must be finite numbers");
|
|
140
|
+
if (est.min < 1 || est.max < est.min) throw new Error("meta.estimatedAgents requires min >= 1 and max >= min");
|
|
141
|
+
}
|
|
133
142
|
}
|
|
134
143
|
//#endregion
|
|
135
144
|
export { parseWorkflowScript };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","names":[],"sources":["../../../../src/agent/workflow/parser.ts"],"sourcesContent":["/**\n * Workflow script parser.\n *\n * Responsibilities:\n * 1. Parse the script with acorn (latest ECMA, top-level await + return allowed).\n * 2. Enforce determinism — reject `Date.now()`, `Math.random()`, `new Date()`,\n * `require`, `import`, dynamic eval. This keeps future resume/replay possible\n * and surfaces non-deterministic mistakes early.\n * 3. Require the first statement to be `export const meta = <literal>`, validate\n * the literal shape, and strip that line from the body returned to the runtime.\n *\n * Returning a `{ meta, body }` pair means the runtime can `vm.Script(body)` without\n * any further AST work.\n */\n\nimport { parse } from 'acorn';\nimport type { Node } from 'acorn';\n\nimport type { WorkflowMeta, WorkflowMetaPhase } from './types.js';\n\ntype AnyNode = Node & { [key: string]: any; start: number; end: number };\n\nconst NONDETERMINISM_ERROR =\n 'Workflow scripts must be deterministic: Date.now()/Math.random()/new Date() are unavailable. ' +\n 'Pass timestamps via args or stamp them after the workflow returns.';\n\nexport interface ParsedWorkflow {\n meta: WorkflowMeta;\n body: string;\n}\n\nexport function parseWorkflowScript(script: string): ParsedWorkflow {\n let ast: AnyNode;\n try {\n ast = parse(script, {\n ecmaVersion: 'latest',\n sourceType: 'module',\n allowAwaitOutsideFunction: true,\n allowReturnOutsideFunction: true,\n ranges: false,\n }) as AnyNode;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`Workflow script parse error: ${msg}`);\n }\n\n assertDeterministicAst(ast);\n assertNoDangerousImports(ast);\n\n const first = ast.body?.[0] as AnyNode | undefined;\n if (first?.type !== 'ExportNamedDeclaration') {\n throw new Error(\n '`export const meta = { name, description }` must be the first statement in the script',\n );\n }\n\n const declaration = first.declaration as AnyNode | null;\n if (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') {\n throw new Error('meta export must be `export const meta = ...`');\n }\n if (declaration.declarations.length !== 1) {\n throw new Error('meta export must declare only `meta`');\n }\n const declarator = declaration.declarations[0] as AnyNode;\n if (declarator.id?.type !== 'Identifier' || declarator.id.name !== 'meta') {\n throw new Error('meta export must declare `meta`');\n }\n if (!declarator.init) {\n throw new Error('meta must have a literal value');\n }\n\n const meta = evaluateLiteral(declarator.init, 'meta');\n validateMeta(meta);\n\n return {\n meta,\n body: script.slice(0, first.start) + script.slice(first.end),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Determinism / safety guards\n// ---------------------------------------------------------------------------\n\nfunction assertDeterministicAst(node: AnyNode): void {\n if (isDateNowCall(node) || isMathRandomCall(node) || isNewDateExpression(node)) {\n throw new Error(NONDETERMINISM_ERROR);\n }\n for (const child of astChildren(node)) {\n assertDeterministicAst(child);\n }\n}\n\nfunction assertNoDangerousImports(node: AnyNode): void {\n if (node.type === 'ImportDeclaration' || node.type === 'ImportExpression') {\n throw new Error(\n \"Workflow scripts cannot use `import` — only the exposed globals (agent, parallel, pipeline, phase, log, args, cwd, budget) are available.\",\n );\n }\n if (node.type === 'CallExpression') {\n const callee = node.callee as AnyNode | undefined;\n if (callee?.type === 'Identifier' && (callee.name === 'require' || callee.name === 'eval')) {\n throw new Error(`Workflow scripts cannot call \\`${callee.name}\\`.`);\n }\n }\n for (const child of astChildren(node)) {\n assertNoDangerousImports(child);\n }\n}\n\nfunction astChildren(node: AnyNode): AnyNode[] {\n const children: AnyNode[] = [];\n for (const value of Object.values(node)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n if (isAstNode(v)) children.push(v);\n }\n } else if (isAstNode(value)) {\n children.push(value);\n }\n }\n return children;\n}\n\nfunction isAstNode(value: unknown): value is AnyNode {\n return !!value && typeof value === 'object' && typeof (value as AnyNode).type === 'string';\n}\n\nfunction isDateNowCall(node: AnyNode): boolean {\n return node.type === 'CallExpression' && isMemberExpression(node.callee, 'Date', 'now');\n}\n\nfunction isMathRandomCall(node: AnyNode): boolean {\n return node.type === 'CallExpression' && isMemberExpression(node.callee, 'Math', 'random');\n}\n\nfunction isNewDateExpression(node: AnyNode): boolean {\n return (\n node.type === 'NewExpression' &&\n (node.callee as AnyNode | undefined)?.type === 'Identifier' &&\n (node.callee as AnyNode).name === 'Date'\n );\n}\n\nfunction isMemberExpression(\n node: AnyNode | undefined,\n objectName: string,\n propertyName: string,\n): boolean {\n if (\n node?.type !== 'MemberExpression' ||\n (node.object as AnyNode | undefined)?.type !== 'Identifier' ||\n (node.object as AnyNode).name !== objectName\n ) {\n return false;\n }\n const prop = node.property as AnyNode | undefined;\n if (!node.computed && prop?.type === 'Identifier') return prop.name === propertyName;\n if (prop?.type === 'Literal' && typeof prop.value === 'string') return prop.value === propertyName;\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Literal evaluator (meta must be a pure literal)\n// ---------------------------------------------------------------------------\n\nfunction evaluateLiteral(node: AnyNode, path: string): any {\n switch (node.type) {\n case 'ObjectExpression': {\n const out: Record<string, unknown> = {};\n for (const prop of node.properties as AnyNode[]) {\n if (prop.type === 'SpreadElement') {\n throw new Error(`spread not allowed in ${path}`);\n }\n if (prop.type !== 'Property') {\n throw new Error(`only plain properties allowed in ${path}`);\n }\n if (prop.computed) {\n throw new Error(`computed keys not allowed in ${path}`);\n }\n if (prop.kind !== 'init' || prop.method) {\n throw new Error(`methods/accessors not allowed in ${path}`);\n }\n const key = propertyKey(prop.key as AnyNode, path);\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n throw new Error(`reserved key name not allowed in ${path}: ${key}`);\n }\n out[key] = evaluateLiteral(prop.value as AnyNode, `${path}.${key}`);\n }\n return out;\n }\n case 'ArrayExpression':\n return (node.elements as Array<AnyNode | null>).map((element, index) => {\n if (!element) throw new Error(`sparse arrays not allowed in ${path}`);\n if (element.type === 'SpreadElement') {\n throw new Error(`spread not allowed in ${path}`);\n }\n return evaluateLiteral(element, `${path}[${index}]`);\n });\n case 'Literal':\n return node.value;\n case 'TemplateLiteral':\n if (node.expressions.length > 0) {\n throw new Error(`template interpolation not allowed in ${path}`);\n }\n return node.quasis\n .map((quasi: AnyNode) => quasi.value.cooked ?? quasi.value.raw)\n .join('');\n case 'UnaryExpression':\n if (\n node.operator === '-' &&\n node.argument?.type === 'Literal' &&\n typeof node.argument.value === 'number'\n ) {\n return -node.argument.value;\n }\n throw new Error(`only negative-number unary allowed in ${path}`);\n default:\n throw new Error(`non-literal node type in ${path}: ${node.type}`);\n }\n}\n\nfunction propertyKey(node: AnyNode, path: string): string {\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && (typeof node.value === 'string' || typeof node.value === 'number')) {\n return String(node.value);\n }\n throw new Error(`unsupported key type in ${path}: ${node.type}`);\n}\n\nfunction validateMeta(meta: unknown): asserts meta is WorkflowMeta {\n if (!meta || typeof meta !== 'object') {\n throw new Error('meta must be an object');\n }\n const value = meta as WorkflowMeta;\n if (typeof value.name !== 'string' || !value.name.trim()) {\n throw new Error('meta.name must be a non-empty string');\n }\n if (!/^[a-z][a-z0-9_-]*$/.test(value.name)) {\n throw new Error(\n `meta.name must be lowercase snake_case (got \"${value.name}\"). Example: \"audit_repo\".`,\n );\n }\n if (typeof value.description !== 'string' || !value.description.trim()) {\n throw new Error('meta.description must be a non-empty string');\n }\n if (value.whenToUse !== undefined && typeof value.whenToUse !== 'string') {\n throw new Error('meta.whenToUse must be a string');\n }\n if (value.phases !== undefined) {\n if (!Array.isArray(value.phases)) {\n throw new Error('meta.phases must be an array');\n }\n for (const phase of value.phases) {\n if (!phase || typeof phase !== 'object' || typeof (phase as WorkflowMetaPhase).title !== 'string') {\n throw new Error('each meta phase must have a title string');\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsBA,MAAM,uBACJ;AAQF,SAAgB,oBAAoB,QAAgC;CAClE,IAAI;AACJ,KAAI;AACF,QAAM,MAAM,QAAQ;GAClB,aAAa;GACb,YAAY;GACZ,2BAA2B;GAC3B,4BAA4B;GAC5B,QAAQ;GACT,CAAC;UACK,GAAG;EACV,MAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AACtD,QAAM,IAAI,MAAM,gCAAgC,MAAM;;AAGxD,wBAAuB,IAAI;AAC3B,0BAAyB,IAAI;CAE7B,MAAM,QAAQ,IAAI,OAAO;AACzB,KAAI,OAAO,SAAS,yBAClB,OAAM,IAAI,MACR,wFACD;CAGH,MAAM,cAAc,MAAM;AAC1B,KAAI,aAAa,SAAS,yBAAyB,YAAY,SAAS,QACtE,OAAM,IAAI,MAAM,gDAAgD;AAElE,KAAI,YAAY,aAAa,WAAW,EACtC,OAAM,IAAI,MAAM,uCAAuC;CAEzD,MAAM,aAAa,YAAY,aAAa;AAC5C,KAAI,WAAW,IAAI,SAAS,gBAAgB,WAAW,GAAG,SAAS,OACjE,OAAM,IAAI,MAAM,kCAAkC;AAEpD,KAAI,CAAC,WAAW,KACd,OAAM,IAAI,MAAM,iCAAiC;CAGnD,MAAM,OAAO,gBAAgB,WAAW,MAAM,OAAO;AACrD,cAAa,KAAK;AAElB,QAAO;EACL;EACA,MAAM,OAAO,MAAM,GAAG,MAAM,MAAM,GAAG,OAAO,MAAM,MAAM,IAAI;EAC7D;;AAOH,SAAS,uBAAuB,MAAqB;AACnD,KAAI,cAAc,KAAK,IAAI,iBAAiB,KAAK,IAAI,oBAAoB,KAAK,CAC5E,OAAM,IAAI,MAAM,qBAAqB;AAEvC,MAAK,MAAM,SAAS,YAAY,KAAK,CACnC,wBAAuB,MAAM;;AAIjC,SAAS,yBAAyB,MAAqB;AACrD,KAAI,KAAK,SAAS,uBAAuB,KAAK,SAAS,mBACrD,OAAM,IAAI,MACR,4IACD;AAEH,KAAI,KAAK,SAAS,kBAAkB;EAClC,MAAM,SAAS,KAAK;AACpB,MAAI,QAAQ,SAAS,iBAAiB,OAAO,SAAS,aAAa,OAAO,SAAS,QACjF,OAAM,IAAI,MAAM,kCAAkC,OAAO,KAAK,KAAK;;AAGvE,MAAK,MAAM,SAAS,YAAY,KAAK,CACnC,0BAAyB,MAAM;;AAInC,SAAS,YAAY,MAA0B;CAC7C,MAAM,WAAsB,EAAE;AAC9B,MAAK,MAAM,SAAS,OAAO,OAAO,KAAK,CACrC,KAAI,MAAM,QAAQ,MAAM;OACjB,MAAM,KAAK,MACd,KAAI,UAAU,EAAE,CAAE,UAAS,KAAK,EAAE;YAE3B,UAAU,MAAM,CACzB,UAAS,KAAK,MAAM;AAGxB,QAAO;;AAGT,SAAS,UAAU,OAAkC;AACnD,QAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,OAAQ,MAAkB,SAAS;;AAGpF,SAAS,cAAc,MAAwB;AAC7C,QAAO,KAAK,SAAS,oBAAoB,mBAAmB,KAAK,QAAQ,QAAQ,MAAM;;AAGzF,SAAS,iBAAiB,MAAwB;AAChD,QAAO,KAAK,SAAS,oBAAoB,mBAAmB,KAAK,QAAQ,QAAQ,SAAS;;AAG5F,SAAS,oBAAoB,MAAwB;AACnD,QACE,KAAK,SAAS,mBACb,KAAK,QAAgC,SAAS,gBAC9C,KAAK,OAAmB,SAAS;;AAItC,SAAS,mBACP,MACA,YACA,cACS;AACT,KACE,MAAM,SAAS,sBACd,KAAK,QAAgC,SAAS,gBAC9C,KAAK,OAAmB,SAAS,WAElC,QAAO;CAET,MAAM,OAAO,KAAK;AAClB,KAAI,CAAC,KAAK,YAAY,MAAM,SAAS,aAAc,QAAO,KAAK,SAAS;AACxE,KAAI,MAAM,SAAS,aAAa,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK,UAAU;AACtF,QAAO;;AAOT,SAAS,gBAAgB,MAAe,MAAmB;AACzD,SAAQ,KAAK,MAAb;EACE,KAAK,oBAAoB;GACvB,MAAM,MAA+B,EAAE;AACvC,QAAK,MAAM,QAAQ,KAAK,YAAyB;AAC/C,QAAI,KAAK,SAAS,gBAChB,OAAM,IAAI,MAAM,yBAAyB,OAAO;AAElD,QAAI,KAAK,SAAS,WAChB,OAAM,IAAI,MAAM,oCAAoC,OAAO;AAE7D,QAAI,KAAK,SACP,OAAM,IAAI,MAAM,gCAAgC,OAAO;AAEzD,QAAI,KAAK,SAAS,UAAU,KAAK,OAC/B,OAAM,IAAI,MAAM,oCAAoC,OAAO;IAE7D,MAAM,MAAM,YAAY,KAAK,KAAgB,KAAK;AAClD,QAAI,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ,YAC1D,OAAM,IAAI,MAAM,oCAAoC,KAAK,IAAI,MAAM;AAErE,QAAI,OAAO,gBAAgB,KAAK,OAAkB,GAAG,KAAK,GAAG,MAAM;;AAErE,UAAO;;EAET,KAAK,kBACH,QAAQ,KAAK,SAAmC,KAAK,SAAS,UAAU;AACtE,OAAI,CAAC,QAAS,OAAM,IAAI,MAAM,gCAAgC,OAAO;AACrE,OAAI,QAAQ,SAAS,gBACnB,OAAM,IAAI,MAAM,yBAAyB,OAAO;AAElD,UAAO,gBAAgB,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG;IACpD;EACJ,KAAK,UACH,QAAO,KAAK;EACd,KAAK;AACH,OAAI,KAAK,YAAY,SAAS,EAC5B,OAAM,IAAI,MAAM,yCAAyC,OAAO;AAElE,UAAO,KAAK,OACT,KAAK,UAAmB,MAAM,MAAM,UAAU,MAAM,MAAM,IAAI,CAC9D,KAAK,GAAG;EACb,KAAK;AACH,OACE,KAAK,aAAa,OAClB,KAAK,UAAU,SAAS,aACxB,OAAO,KAAK,SAAS,UAAU,SAE/B,QAAO,CAAC,KAAK,SAAS;AAExB,SAAM,IAAI,MAAM,yCAAyC,OAAO;EAClE,QACE,OAAM,IAAI,MAAM,4BAA4B,KAAK,IAAI,KAAK,OAAO;;;AAIvE,SAAS,YAAY,MAAe,MAAsB;AACxD,KAAI,KAAK,SAAS,aAAc,QAAO,KAAK;AAC5C,KAAI,KAAK,SAAS,cAAc,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,UAAU,UACtF,QAAO,OAAO,KAAK,MAAM;AAE3B,OAAM,IAAI,MAAM,2BAA2B,KAAK,IAAI,KAAK,OAAO;;AAGlE,SAAS,aAAa,MAA6C;AACjE,KAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,OAAM,IAAI,MAAM,yBAAyB;CAE3C,MAAM,QAAQ;AACd,KAAI,OAAO,MAAM,SAAS,YAAY,CAAC,MAAM,KAAK,MAAM,CACtD,OAAM,IAAI,MAAM,uCAAuC;AAEzD,KAAI,CAAC,qBAAqB,KAAK,MAAM,KAAK,CACxC,OAAM,IAAI,MACR,gDAAgD,MAAM,KAAK,4BAC5D;AAEH,KAAI,OAAO,MAAM,gBAAgB,YAAY,CAAC,MAAM,YAAY,MAAM,CACpE,OAAM,IAAI,MAAM,8CAA8C;AAEhE,KAAI,MAAM,cAAc,KAAA,KAAa,OAAO,MAAM,cAAc,SAC9D,OAAM,IAAI,MAAM,kCAAkC;AAEpD,KAAI,MAAM,WAAW,KAAA,GAAW;AAC9B,MAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,CAC9B,OAAM,IAAI,MAAM,+BAA+B;AAEjD,OAAK,MAAM,SAAS,MAAM,OACxB,KAAI,CAAC,SAAS,OAAO,UAAU,YAAY,OAAQ,MAA4B,UAAU,SACvF,OAAM,IAAI,MAAM,2CAA2C"}
|
|
1
|
+
{"version":3,"file":"parser.js","names":[],"sources":["../../../../src/agent/workflow/parser.ts"],"sourcesContent":["/**\n * Workflow script parser.\n *\n * Responsibilities:\n * 1. Parse the script with acorn (latest ECMA, top-level await + return allowed).\n * 2. Enforce determinism — reject `Date.now()`, `Math.random()`, `new Date()`,\n * `require`, `import`, dynamic eval. This keeps future resume/replay possible\n * and surfaces non-deterministic mistakes early.\n * 3. Require the first statement to be `export const meta = <literal>`, validate\n * the literal shape, and strip that line from the body returned to the runtime.\n *\n * Returning a `{ meta, body }` pair means the runtime can `vm.Script(body)` without\n * any further AST work.\n */\n\nimport { parse } from 'acorn';\nimport type { Node } from 'acorn';\n\nimport type { WorkflowMeta, WorkflowMetaPhase } from './types.js';\n\ntype AnyNode = Node & { [key: string]: any; start: number; end: number };\n\nconst NONDETERMINISM_ERROR =\n 'Workflow scripts must be deterministic: Date.now()/Math.random()/new Date() are unavailable. ' +\n 'Pass timestamps via args or stamp them after the workflow returns.';\n\nexport interface ParsedWorkflow {\n meta: WorkflowMeta;\n body: string;\n}\n\nexport function parseWorkflowScript(script: string): ParsedWorkflow {\n let ast: AnyNode;\n try {\n ast = parse(script, {\n ecmaVersion: 'latest',\n sourceType: 'module',\n allowAwaitOutsideFunction: true,\n allowReturnOutsideFunction: true,\n ranges: false,\n }) as AnyNode;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`Workflow script parse error: ${msg}`);\n }\n\n assertDeterministicAst(ast);\n assertNoDangerousImports(ast);\n\n const first = ast.body?.[0] as AnyNode | undefined;\n if (first?.type !== 'ExportNamedDeclaration') {\n throw new Error(\n '`export const meta = { name, description }` must be the first statement in the script',\n );\n }\n\n const declaration = first.declaration as AnyNode | null;\n if (declaration?.type !== 'VariableDeclaration' || declaration.kind !== 'const') {\n throw new Error('meta export must be `export const meta = ...`');\n }\n if (declaration.declarations.length !== 1) {\n throw new Error('meta export must declare only `meta`');\n }\n const declarator = declaration.declarations[0] as AnyNode;\n if (declarator.id?.type !== 'Identifier' || declarator.id.name !== 'meta') {\n throw new Error('meta export must declare `meta`');\n }\n if (!declarator.init) {\n throw new Error('meta must have a literal value');\n }\n\n const meta = evaluateLiteral(declarator.init, 'meta');\n validateMeta(meta);\n\n return {\n meta,\n body: script.slice(0, first.start) + script.slice(first.end),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Determinism / safety guards\n// ---------------------------------------------------------------------------\n\nfunction assertDeterministicAst(node: AnyNode): void {\n if (isDateNowCall(node) || isMathRandomCall(node) || isNewDateExpression(node)) {\n throw new Error(NONDETERMINISM_ERROR);\n }\n for (const child of astChildren(node)) {\n assertDeterministicAst(child);\n }\n}\n\nfunction assertNoDangerousImports(node: AnyNode): void {\n if (node.type === 'ImportDeclaration' || node.type === 'ImportExpression') {\n throw new Error(\n \"Workflow scripts cannot use `import` — only the exposed globals (agent, parallel, pipeline, phase, log, args, cwd, budget) are available.\",\n );\n }\n if (node.type === 'CallExpression') {\n const callee = node.callee as AnyNode | undefined;\n if (callee?.type === 'Identifier' && (callee.name === 'require' || callee.name === 'eval')) {\n throw new Error(`Workflow scripts cannot call \\`${callee.name}\\`.`);\n }\n }\n for (const child of astChildren(node)) {\n assertNoDangerousImports(child);\n }\n}\n\nfunction astChildren(node: AnyNode): AnyNode[] {\n const children: AnyNode[] = [];\n for (const value of Object.values(node)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n if (isAstNode(v)) children.push(v);\n }\n } else if (isAstNode(value)) {\n children.push(value);\n }\n }\n return children;\n}\n\nfunction isAstNode(value: unknown): value is AnyNode {\n return !!value && typeof value === 'object' && typeof (value as AnyNode).type === 'string';\n}\n\nfunction isDateNowCall(node: AnyNode): boolean {\n return node.type === 'CallExpression' && isMemberExpression(node.callee, 'Date', 'now');\n}\n\nfunction isMathRandomCall(node: AnyNode): boolean {\n return node.type === 'CallExpression' && isMemberExpression(node.callee, 'Math', 'random');\n}\n\nfunction isNewDateExpression(node: AnyNode): boolean {\n return (\n node.type === 'NewExpression' &&\n (node.callee as AnyNode | undefined)?.type === 'Identifier' &&\n (node.callee as AnyNode).name === 'Date'\n );\n}\n\nfunction isMemberExpression(\n node: AnyNode | undefined,\n objectName: string,\n propertyName: string,\n): boolean {\n if (\n node?.type !== 'MemberExpression' ||\n (node.object as AnyNode | undefined)?.type !== 'Identifier' ||\n (node.object as AnyNode).name !== objectName\n ) {\n return false;\n }\n const prop = node.property as AnyNode | undefined;\n if (!node.computed && prop?.type === 'Identifier') return prop.name === propertyName;\n if (prop?.type === 'Literal' && typeof prop.value === 'string') return prop.value === propertyName;\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Literal evaluator (meta must be a pure literal)\n// ---------------------------------------------------------------------------\n\nfunction evaluateLiteral(node: AnyNode, path: string): any {\n switch (node.type) {\n case 'ObjectExpression': {\n const out: Record<string, unknown> = {};\n for (const prop of node.properties as AnyNode[]) {\n if (prop.type === 'SpreadElement') {\n throw new Error(`spread not allowed in ${path}`);\n }\n if (prop.type !== 'Property') {\n throw new Error(`only plain properties allowed in ${path}`);\n }\n if (prop.computed) {\n throw new Error(`computed keys not allowed in ${path}`);\n }\n if (prop.kind !== 'init' || prop.method) {\n throw new Error(`methods/accessors not allowed in ${path}`);\n }\n const key = propertyKey(prop.key as AnyNode, path);\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n throw new Error(`reserved key name not allowed in ${path}: ${key}`);\n }\n out[key] = evaluateLiteral(prop.value as AnyNode, `${path}.${key}`);\n }\n return out;\n }\n case 'ArrayExpression':\n return (node.elements as Array<AnyNode | null>).map((element, index) => {\n if (!element) throw new Error(`sparse arrays not allowed in ${path}`);\n if (element.type === 'SpreadElement') {\n throw new Error(`spread not allowed in ${path}`);\n }\n return evaluateLiteral(element, `${path}[${index}]`);\n });\n case 'Literal':\n return node.value;\n case 'TemplateLiteral':\n if (node.expressions.length > 0) {\n throw new Error(`template interpolation not allowed in ${path}`);\n }\n return node.quasis\n .map((quasi: AnyNode) => quasi.value.cooked ?? quasi.value.raw)\n .join('');\n case 'UnaryExpression':\n if (\n node.operator === '-' &&\n node.argument?.type === 'Literal' &&\n typeof node.argument.value === 'number'\n ) {\n return -node.argument.value;\n }\n throw new Error(`only negative-number unary allowed in ${path}`);\n default:\n throw new Error(`non-literal node type in ${path}: ${node.type}`);\n }\n}\n\nfunction propertyKey(node: AnyNode, path: string): string {\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && (typeof node.value === 'string' || typeof node.value === 'number')) {\n return String(node.value);\n }\n throw new Error(`unsupported key type in ${path}: ${node.type}`);\n}\n\nfunction validateMeta(meta: unknown): asserts meta is WorkflowMeta {\n if (!meta || typeof meta !== 'object') {\n throw new Error('meta must be an object');\n }\n const value = meta as WorkflowMeta;\n if (typeof value.name !== 'string' || !value.name.trim()) {\n throw new Error('meta.name must be a non-empty string');\n }\n if (!/^[a-z][a-z0-9_-]*$/.test(value.name)) {\n throw new Error(\n `meta.name must be lowercase snake_case (got \"${value.name}\"). Example: \"audit_repo\".`,\n );\n }\n if (typeof value.description !== 'string' || !value.description.trim()) {\n throw new Error('meta.description must be a non-empty string');\n }\n if (value.whenToUse !== undefined && typeof value.whenToUse !== 'string') {\n throw new Error('meta.whenToUse must be a string');\n }\n if (value.phases !== undefined) {\n if (!Array.isArray(value.phases)) {\n throw new Error('meta.phases must be an array');\n }\n for (const phase of value.phases) {\n if (!phase || typeof phase !== 'object' || typeof (phase as WorkflowMetaPhase).title !== 'string') {\n throw new Error('each meta phase must have a title string');\n }\n }\n }\n if (value.tags !== undefined) {\n if (!Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== 'string' || !tag.trim())) {\n throw new Error('meta.tags must be an array of non-empty strings');\n }\n }\n if (value.estimatedAgents !== undefined) {\n const est = value.estimatedAgents;\n if (!est || typeof est !== 'object') {\n throw new Error('meta.estimatedAgents must be an object');\n }\n if (typeof est.min !== 'number' || typeof est.max !== 'number' || !Number.isFinite(est.min) || !Number.isFinite(est.max)) {\n throw new Error('meta.estimatedAgents.min and .max must be finite numbers');\n }\n if (est.min < 1 || est.max < est.min) {\n throw new Error('meta.estimatedAgents requires min >= 1 and max >= min');\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -24,11 +24,19 @@ export interface WorkflowMetaPhase {
|
|
|
24
24
|
detail?: string;
|
|
25
25
|
model?: string;
|
|
26
26
|
}
|
|
27
|
+
export interface WorkflowMetaEstimatedAgents {
|
|
28
|
+
min: number;
|
|
29
|
+
max: number;
|
|
30
|
+
}
|
|
27
31
|
export interface WorkflowMeta {
|
|
28
32
|
name: string;
|
|
29
33
|
description: string;
|
|
30
34
|
whenToUse?: string;
|
|
31
35
|
phases?: WorkflowMetaPhase[];
|
|
36
|
+
/** Discovery tags, e.g. `['code-review', 'planning']`. */
|
|
37
|
+
tags?: string[];
|
|
38
|
+
/** Rough subagent count range for UX / cost hints. */
|
|
39
|
+
estimatedAgents?: WorkflowMetaEstimatedAgents;
|
|
32
40
|
}
|
|
33
41
|
export type WorkflowAgentStatus = 'queued' | 'running' | 'done' | 'error' | 'skipped';
|
|
34
42
|
export interface WorkflowAgentSnapshot {
|
|
@@ -19,6 +19,11 @@ import { bulletList, code, joinBlocks, section } from "../format-output.js";
|
|
|
19
19
|
* piece.
|
|
20
20
|
*/
|
|
21
21
|
const VIEW_MAX_LINES = 200;
|
|
22
|
+
function formatEntryDetail(entry) {
|
|
23
|
+
const tags = entry.tags?.length ? `[${entry.tags.join(", ")}] ` : "";
|
|
24
|
+
const agents = entry.estimatedAgents ? ` (~${entry.estimatedAgents.min}–${entry.estimatedAgents.max} agents)` : "";
|
|
25
|
+
return `${tags}${entry.description}${agents}`;
|
|
26
|
+
}
|
|
22
27
|
function formatWorkflowListContent(entries, userDir) {
|
|
23
28
|
const grouped = {
|
|
24
29
|
builtin: entries.filter((e) => e.source === "builtin"),
|
|
@@ -28,11 +33,11 @@ function formatWorkflowListContent(entries, userDir) {
|
|
|
28
33
|
const blocks = [];
|
|
29
34
|
if (grouped.user.length > 0) blocks.push(joinBlocks(section("User workflows"), bulletList(grouped.user.map((e) => ({
|
|
30
35
|
label: e.name,
|
|
31
|
-
detail: e
|
|
36
|
+
detail: formatEntryDetail(e)
|
|
32
37
|
})))));
|
|
33
38
|
if (grouped.builtin.length > 0) blocks.push(joinBlocks(section("Built-in workflows"), bulletList(grouped.builtin.map((e) => ({
|
|
34
39
|
label: e.name,
|
|
35
|
-
detail: e
|
|
40
|
+
detail: formatEntryDetail(e)
|
|
36
41
|
})))));
|
|
37
42
|
blocks.push(joinBlocks(section("How to run"), bulletList([
|
|
38
43
|
`Plain language: "run the ${exampleName} workflow"`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.js","names":[],"sources":["../../../../src/chat-commands/builtins/workflow.ts"],"sourcesContent":["/**\n * `/workflows` and `/workflow <subcommand>` — read-only commands for browsing\n * saved workflows.\n *\n * Why only read commands here? Slash command results are sent to the user; they\n * are NOT injected back into the agent's turn. Triggering a workflow run from\n * the slash layer would require a non-trivial cross-cutting \"inject this as the\n * next user message\" hook that doesn't exist yet. Instead, the workflow tool\n * understands `name`, and its description tells the model to prefer that route\n * whenever a user mentions a saved workflow by name. Plain text — \"run the\n * audit_repo workflow\" — works end-to-end.\n *\n * `/workflows` and `/workflow view` make discovery cheap, which is the missing\n * piece.\n */\n\nimport { commandRegistry } from '../registry.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { bulletList, code, joinBlocks, section } from '../format-output.js';\n\nimport { createWorkflowCatalog } from '../../agent/workflow/catalog.js';\nimport { getLastWorkflowMemory } from '../../agent/workflow/last-run-memory.js';\nimport type { CatalogEntry } from '../../agent/workflow/catalog.js';\n\nconst VIEW_MAX_LINES = 200;\n\nfunction formatWorkflowListContent(entries: CatalogEntry[], userDir: string): string {\n const grouped = {\n builtin: entries.filter((e) => e.source === 'builtin'),\n user: entries.filter((e) => e.source === 'user'),\n };\n const exampleName = entries[0]?.name ?? 'audit_repo';\n const blocks: string[] = [];\n\n if (grouped.user.length > 0) {\n blocks.push(\n joinBlocks(\n section('User workflows'),\n bulletList(grouped.user.map((e) => ({ label: e.name, detail: e.description }))),\n ),\n );\n }\n if (grouped.builtin.length > 0) {\n blocks.push(\n joinBlocks(\n section('Built-in workflows'),\n bulletList(grouped.builtin.map((e) => ({ label: e.name, detail: e.description }))),\n ),\n );\n }\n\n blocks.push(\n joinBlocks(\n section('How to run'),\n bulletList([\n `Plain language: \"run the ${exampleName} workflow\"`,\n `Inspect source: ${code(`/workflow view ${exampleName}`)}`,\n `Add your own: drop a ${code('.js')} at ${code(userDir)}`,\n ]),\n ),\n );\n\n return joinBlocks(...blocks);\n}\n\nconst workflowsCommand: CommandDefinition = {\n id: 'system.workflows',\n name: 'workflows',\n description: 'List saved workflows (built-in + ~/.xopc/workflows/)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const catalog = createWorkflowCatalog();\n const entries = catalog.list();\n if (entries.length === 0) {\n return {\n content: `No workflows found. Drop a script at ${code(`${catalog.userDir}/<name>.js`)} to add one.`,\n success: true,\n };\n }\n return { content: formatWorkflowListContent(entries, catalog.userDir), success: true };\n },\n};\n\nexport const workflowCommand: CommandDefinition = {\n id: 'system.workflow',\n name: 'workflow',\n description: 'Inspect or manage saved workflows. Subcommands: list, view <name>',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/workflow list', '/workflow view audit_repo'],\n handler: async (ctx: CommandContext, args: string) => {\n const trimmed = args.trim();\n if (!trimmed || trimmed.toLowerCase() === 'list') {\n return workflowsCommand.handler(ctx, '');\n }\n const [sub, ...rest] = trimmed.split(/\\s+/);\n const subLower = sub.toLowerCase();\n const target = rest.join(' ').trim();\n\n if (subLower === 'view' || subLower === 'show' || subLower === 'cat') {\n if (!target) {\n return { content: `usage: ${code('/workflow view <name>')}`, success: false };\n }\n const catalog = createWorkflowCatalog();\n try {\n const loaded = catalog.load(target);\n const lines = loaded.script.split('\\n');\n const visible =\n lines.length > VIEW_MAX_LINES\n ? [...lines.slice(0, VIEW_MAX_LINES), `… (truncated; ${lines.length - VIEW_MAX_LINES} more lines)`]\n : lines;\n const source = loaded.source === 'user' ? loaded.path ?? 'user' : 'built-in';\n return {\n content: joinBlocks(\n `**${loaded.name}** (${source}) — ${loaded.meta.description}`,\n '```js\\n' + visible.join('\\n') + '\\n```',\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n if (subLower === 'run' || subLower === 'start') {\n const name = target || '<name>';\n return {\n content: joinBlocks(\n `To run a workflow, ask in plain language: \"run the ${name} workflow\".`,\n `The assistant will call the workflow tool with ${code(`name=\"${name}\"`)} and stream progress inline.`,\n ),\n success: true,\n };\n }\n\n if (subLower === 'save') {\n if (!target) {\n return { content: `usage: ${code('/workflow save <name>')}`, success: false };\n }\n const last = getLastWorkflowMemory().get(ctx.sessionKey);\n if (!last) {\n return {\n content:\n 'No workflow has run successfully in this session yet. Run one first (e.g. ask \"run the audit_repo workflow\"), then `/workflow save <name>`.',\n success: false,\n };\n }\n const catalog = createWorkflowCatalog();\n try {\n // Allow the user to rename: if target differs from meta.name, rewrite it\n // before saving so the file is addressable as `target`.\n const script =\n last.metaName === target ? last.script : rewriteMetaName(last.script, target);\n const { path } = catalog.save(target, script);\n return {\n content: joinBlocks(\n `✓ Saved workflow **${target}** → ${code(path)}`,\n bulletList([\n `Trigger with ${code(`/${target}`)} or \"run the ${target} workflow\"`,\n `Inspect with ${code(`/workflow view ${target}`)}`,\n ]),\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n return {\n content: joinBlocks(\n `Unknown subcommand \"${sub}\". Available: list, view ${code('<name>')}, save ${code('<name>')}.`,\n 'To run a workflow, ask in plain language (\"run the audit_repo workflow\") — the assistant uses the workflow tool with `name=\"...\"`.',\n ),\n success: false,\n };\n },\n};\n\n/**\n * Replace the `name` field inside the FIRST `export const meta = { ... }` literal.\n *\n * Why text-level (not AST re-emit)? The parser already accepted the script\n * once (the runtime ran it), so the surrounding code is unchanged. A targeted\n * regex on the `name: '...'` slot inside the first object literal keeps the\n * user's formatting / comments / quote style intact, which an AST round-trip\n * would smash. The match anchors to the first `name:` after `export const meta`\n * and only touches that single value.\n */\nfunction rewriteMetaName(script: string, newName: string): string {\n const re = /(export\\s+const\\s+meta\\s*=\\s*\\{[^}]*?\\bname\\s*:\\s*)(['\"`])([^'\"`]*)\\2/;\n if (!re.test(script)) {\n throw new Error('could not locate meta.name in the recorded script to rewrite');\n }\n return script.replace(re, (_m, prefix, quote) => `${prefix}${quote}${newName}${quote}`);\n}\n\nexport function registerWorkflowCommands(): void {\n commandRegistry.register(workflowsCommand);\n commandRegistry.register(workflowCommand);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflow.js","names":[],"sources":["../../../../src/chat-commands/builtins/workflow.ts"],"sourcesContent":["/**\n * `/workflows` and `/workflow <subcommand>` — read-only commands for browsing\n * saved workflows.\n *\n * Why only read commands here? Slash command results are sent to the user; they\n * are NOT injected back into the agent's turn. Triggering a workflow run from\n * the slash layer would require a non-trivial cross-cutting \"inject this as the\n * next user message\" hook that doesn't exist yet. Instead, the workflow tool\n * understands `name`, and its description tells the model to prefer that route\n * whenever a user mentions a saved workflow by name. Plain text — \"run the\n * audit_repo workflow\" — works end-to-end.\n *\n * `/workflows` and `/workflow view` make discovery cheap, which is the missing\n * piece.\n */\n\nimport { commandRegistry } from '../registry.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { bulletList, code, joinBlocks, section } from '../format-output.js';\n\nimport { createWorkflowCatalog } from '../../agent/workflow/catalog.js';\nimport { getLastWorkflowMemory } from '../../agent/workflow/last-run-memory.js';\nimport type { CatalogEntry } from '../../agent/workflow/catalog.js';\n\nconst VIEW_MAX_LINES = 200;\n\nfunction formatEntryDetail(entry: CatalogEntry): string {\n const tags = entry.tags?.length ? `[${entry.tags.join(', ')}] ` : '';\n const agents = entry.estimatedAgents\n ? ` (~${entry.estimatedAgents.min}–${entry.estimatedAgents.max} agents)`\n : '';\n return `${tags}${entry.description}${agents}`;\n}\n\nfunction formatWorkflowListContent(entries: CatalogEntry[], userDir: string): string {\n const grouped = {\n builtin: entries.filter((e) => e.source === 'builtin'),\n user: entries.filter((e) => e.source === 'user'),\n };\n const exampleName = entries[0]?.name ?? 'audit_repo';\n const blocks: string[] = [];\n\n if (grouped.user.length > 0) {\n blocks.push(\n joinBlocks(\n section('User workflows'),\n bulletList(grouped.user.map((e) => ({ label: e.name, detail: formatEntryDetail(e) }))),\n ),\n );\n }\n if (grouped.builtin.length > 0) {\n blocks.push(\n joinBlocks(\n section('Built-in workflows'),\n bulletList(grouped.builtin.map((e) => ({ label: e.name, detail: formatEntryDetail(e) }))),\n ),\n );\n }\n\n blocks.push(\n joinBlocks(\n section('How to run'),\n bulletList([\n `Plain language: \"run the ${exampleName} workflow\"`,\n `Inspect source: ${code(`/workflow view ${exampleName}`)}`,\n `Add your own: drop a ${code('.js')} at ${code(userDir)}`,\n ]),\n ),\n );\n\n return joinBlocks(...blocks);\n}\n\nconst workflowsCommand: CommandDefinition = {\n id: 'system.workflows',\n name: 'workflows',\n description: 'List saved workflows (built-in + ~/.xopc/workflows/)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const catalog = createWorkflowCatalog();\n const entries = catalog.list();\n if (entries.length === 0) {\n return {\n content: `No workflows found. Drop a script at ${code(`${catalog.userDir}/<name>.js`)} to add one.`,\n success: true,\n };\n }\n return { content: formatWorkflowListContent(entries, catalog.userDir), success: true };\n },\n};\n\nexport const workflowCommand: CommandDefinition = {\n id: 'system.workflow',\n name: 'workflow',\n description: 'Inspect or manage saved workflows. Subcommands: list, view <name>',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/workflow list', '/workflow view audit_repo'],\n handler: async (ctx: CommandContext, args: string) => {\n const trimmed = args.trim();\n if (!trimmed || trimmed.toLowerCase() === 'list') {\n return workflowsCommand.handler(ctx, '');\n }\n const [sub, ...rest] = trimmed.split(/\\s+/);\n const subLower = sub.toLowerCase();\n const target = rest.join(' ').trim();\n\n if (subLower === 'view' || subLower === 'show' || subLower === 'cat') {\n if (!target) {\n return { content: `usage: ${code('/workflow view <name>')}`, success: false };\n }\n const catalog = createWorkflowCatalog();\n try {\n const loaded = catalog.load(target);\n const lines = loaded.script.split('\\n');\n const visible =\n lines.length > VIEW_MAX_LINES\n ? [...lines.slice(0, VIEW_MAX_LINES), `… (truncated; ${lines.length - VIEW_MAX_LINES} more lines)`]\n : lines;\n const source = loaded.source === 'user' ? loaded.path ?? 'user' : 'built-in';\n return {\n content: joinBlocks(\n `**${loaded.name}** (${source}) — ${loaded.meta.description}`,\n '```js\\n' + visible.join('\\n') + '\\n```',\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n if (subLower === 'run' || subLower === 'start') {\n const name = target || '<name>';\n return {\n content: joinBlocks(\n `To run a workflow, ask in plain language: \"run the ${name} workflow\".`,\n `The assistant will call the workflow tool with ${code(`name=\"${name}\"`)} and stream progress inline.`,\n ),\n success: true,\n };\n }\n\n if (subLower === 'save') {\n if (!target) {\n return { content: `usage: ${code('/workflow save <name>')}`, success: false };\n }\n const last = getLastWorkflowMemory().get(ctx.sessionKey);\n if (!last) {\n return {\n content:\n 'No workflow has run successfully in this session yet. Run one first (e.g. ask \"run the audit_repo workflow\"), then `/workflow save <name>`.',\n success: false,\n };\n }\n const catalog = createWorkflowCatalog();\n try {\n // Allow the user to rename: if target differs from meta.name, rewrite it\n // before saving so the file is addressable as `target`.\n const script =\n last.metaName === target ? last.script : rewriteMetaName(last.script, target);\n const { path } = catalog.save(target, script);\n return {\n content: joinBlocks(\n `✓ Saved workflow **${target}** → ${code(path)}`,\n bulletList([\n `Trigger with ${code(`/${target}`)} or \"run the ${target} workflow\"`,\n `Inspect with ${code(`/workflow view ${target}`)}`,\n ]),\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n return {\n content: joinBlocks(\n `Unknown subcommand \"${sub}\". Available: list, view ${code('<name>')}, save ${code('<name>')}.`,\n 'To run a workflow, ask in plain language (\"run the audit_repo workflow\") — the assistant uses the workflow tool with `name=\"...\"`.',\n ),\n success: false,\n };\n },\n};\n\n/**\n * Replace the `name` field inside the FIRST `export const meta = { ... }` literal.\n *\n * Why text-level (not AST re-emit)? The parser already accepted the script\n * once (the runtime ran it), so the surrounding code is unchanged. A targeted\n * regex on the `name: '...'` slot inside the first object literal keeps the\n * user's formatting / comments / quote style intact, which an AST round-trip\n * would smash. The match anchors to the first `name:` after `export const meta`\n * and only touches that single value.\n */\nfunction rewriteMetaName(script: string, newName: string): string {\n const re = /(export\\s+const\\s+meta\\s*=\\s*\\{[^}]*?\\bname\\s*:\\s*)(['\"`])([^'\"`]*)\\2/;\n if (!re.test(script)) {\n throw new Error('could not locate meta.name in the recorded script to rewrite');\n }\n return script.replace(re, (_m, prefix, quote) => `${prefix}${quote}${newName}${quote}`);\n}\n\nexport function registerWorkflowCommands(): void {\n commandRegistry.register(workflowsCommand);\n commandRegistry.register(workflowCommand);\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
|
|
4
|
-
import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
|
|
5
4
|
import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
|
|
6
5
|
import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
|
|
6
|
+
import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
|
|
7
7
|
import { createHeartbeatWake } from "../../heartbeat/wake.js";
|
|
8
8
|
import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
|
|
9
9
|
import { readFile } from "fs/promises";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
|
|
2
|
-
import { appendCronEventLines } from "./event-prompt.js";
|
|
3
2
|
import { isWithinActiveHours } from "./active-hours.js";
|
|
4
3
|
import { isHeartbeatContentEmpty } from "./content-check.js";
|
|
4
|
+
import { appendCronEventLines } from "./event-prompt.js";
|
|
5
5
|
import { createHeartbeatWake } from "./wake.js";
|
|
6
6
|
export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.86",
|
|
4
4
|
"description": "The OPC workstation that grows with you: AI assistant for One Person Companies — CLI, gateway, multi-channel (Telegram/WeChat), 20+ LLM providers via pi-ai, extensions and skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{i,o as a,t as o}from"./url-BwNL6Rgk.js";import{i as s}from"./vendor-swr-BIWyz7Rc.js";import{a as c,n as l,t as u}from"./fetch-B2MYHbWg.js";import{$n as d,En as f,Zn as p,er as m,ii as h,n as g,nr as _,oa as v,tr as y,ua as b}from"./index-D4vM3-P7.js";import{a as x,c as S,d as C,i as w,l as T,s as E,t as D,u as O}from"./voice-api-key-field-Ds51havm.js";import{n as k}from"./field-primitives-Zzl22MvN.js";var A=n(),j=e(t(),1),M=r(),N=()=>o(C);function P(e){return{credentialsIntro:e.credentialsIntro,regionHint:e.regionHint,endpointPresetsHint:e.endpointPresetsHint,apiKeyLabel:e.apiKeyLabel,optionalPlaceholder:e.optionalPlaceholder,regionLabel:e.regionLabel,baseUrlLabel:e.baseUrlLabel,imageBaseUrlLabel:e.imageBaseUrlLabel,saveCredentials:e.saveCredentials,savingCredentials:e.savingCredentials,credentialsSaved:e.credentialsSaved,discardCredentials:e.discardCredentials,credentialsNothingToSave:e.credentialsNothingToSave,credentialsSaveError:e.credentialsSaveError,regionPresetDefault:e.regionPresetDefault,regionPresetCustom:e.regionPresetCustom,baseUrlPresetDefault:e.baseUrlPresetDefault,baseUrlPresetCustom:e.baseUrlPresetCustom,openExtensionSettings:e.openExtensionSettings,openImageModelsPage:e.openImageModelsPage,extensionSettingsLinkTitle:e.extensionSettingsLinkTitle,imageModelsLinkTitle:e.imageModelsLinkTitle,configured:e.configured,missingKey:e.missingKey,unsavedChanges:e.unsavedChanges,expandProvider:e.expandProvider,collapseProvider:e.collapseProvider,defaultModel:e.defaultModel,modelsLabel:e.modelsLabel,modelCountOne:e.modelCountOne,modelCountMany:e.modelCountMany,imageBaseUrlPresetHint:e.imageBaseUrlPresetHint,dashscopeRegion_beijing:e.dashscopeRegion_beijing,dashscopeRegion_singapore:e.dashscopeRegion_singapore,dashscopeRegion_us:e.dashscopeRegion_us,apiKeyMaskedHelp:e.apiKeyMaskedHelp,apiKeyCopy:e.apiKeyCopy,apiKeyCopied:e.apiKeyCopied,apiKeyShow:e.apiKeyShow,apiKeyHide:e.apiKeyHide,apiKeyNotInConfigFile:e.apiKeyNotInConfigFile,apiKeyRevealFailed:e.apiKeyRevealFailed,minimaxClusterLabel:e.minimaxClusterLabel,minimaxClusterHint:e.minimaxClusterHint,falQueueBaseLabel:e.falQueueBaseLabel,falQueueBaseHint:e.falQueueBaseHint}}function F(e){let t=(0,A.c)(40),{extensionId:n}=e,r=i(L),o;t[0]===r?o=t[1]:(o=a(r),t[0]=r,t[1]=o);let l=o,u=l.imageModelsSettings,d=c(I),f;t[2]===d?f=t[3]:(f=d?N():null,t[2]=d,t[3]=f);let p;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(p={revalidateOnFocus:!1},t[4]=p):p=t[4];let{data:m,isLoading:g}=s(f,O,p),_;t[5]===m?_=t[6]:(_=m===void 0?[]:m,t[5]=m,t[6]=_);let v=_,y;if(t[7]!==v||t[8]!==n){let e;t[10]===n?e=t[11]:(e=e=>e.id===n,t[10]=n,t[11]=e),y=v.filter(e),t[7]=v,t[8]=n,t[9]=y}else y=t[9];let b=y,x=S(b),C;t[12]===u?C=t[13]:(C=P(u),t[12]=u,t[13]=C);let w=C,E;t[14]!==l.providersSettings.getApiKey||t[15]!==l.providersSettings.getApiKeyCn||t[16]!==l.providersSettings.getApiKeyIntl?(E={getApiKey:l.providersSettings.getApiKey,getApiKeyIntl:l.providersSettings.getApiKeyIntl,getApiKeyCn:l.providersSettings.getApiKeyCn},t[14]=l.providersSettings.getApiKey,t[15]=l.providersSettings.getApiKeyCn,t[16]=l.providersSettings.getApiKeyIntl,t[17]=E):E=t[17];let D=E;if(!d)return null;if(g){let e;return t[18]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,M.jsxs)(`div`,{className:`flex items-center gap-2 py-6 text-sm text-fg-muted`,children:[(0,M.jsx)(h,{className:`size-4 animate-spin`}),`…`]}),t[18]=e):e=t[18],e}if(b.length===0){let e=r===`zh`?`网关未注册该图像 Provider,或扩展已被禁用。`:`This image provider is not registered on the gateway, or the extension is disabled.`,n;return t[19]===e?n=t[20]:(n=(0,M.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e}),t[19]=e,t[20]=n),n}let k;t[21]!==x||t[22]!==u.credentialsSaveError?(k=()=>void x.saveCredentials(u.credentialsSaveError),t[21]=x,t[22]=u.credentialsSaveError,t[23]=k):k=t[23];let j;t[24]===Symbol.for(`react.memo_cache_sentinel`)?(j=new Set,t[24]=j):j=t[24];let F;return t[25]!==D||t[26]!==x.credBaseline||t[27]!==x.credDirty||t[28]!==x.credDraft||t[29]!==x.credError||t[30]!==x.credNoopFlash||t[31]!==x.credSavedFlash||t[32]!==x.credSaving||t[33]!==x.onDiscardCredentials||t[34]!==x.updateCredRow||t[35]!==r||t[36]!==w||t[37]!==b||t[38]!==k?(F=(0,M.jsx)(T,{summaries:b,credDraft:x.credDraft,credBaseline:x.credBaseline,credDirty:x.credDirty,credSaving:x.credSaving,credError:x.credError,credSavedFlash:x.credSavedFlash,credNoopFlash:x.credNoopFlash,updateCredRow:x.updateCredRow,onDiscardCredentials:x.onDiscardCredentials,onSaveCredentials:k,extensionIds:j,showExtensionLinks:!1,showImageModelsLink:!1,language:r,apiKeyLinkLabels:D,messages:w}),t[25]=D,t[26]=x.credBaseline,t[27]=x.credDirty,t[28]=x.credDraft,t[29]=x.credError,t[30]=x.credNoopFlash,t[31]=x.credSavedFlash,t[32]=x.credSaving,t[33]=x.onDiscardCredentials,t[34]=x.updateCredRow,t[35]=r,t[36]=w,t[37]=b,t[38]=k,t[39]=F):F=t[39],F}function I(e){return!!e.token}function L(e){return e.language}var R=[{id:`whisper-large-v3-turbo`,name:`Whisper Large v3 Turbo`},{id:`whisper-large-v3`,name:`Whisper Large v3`}];function ee(e){let t=e?.manifest?.mediaUnderstandingProviders?.[0];if(typeof t==`string`&&t.trim())return t.trim();let n=e?.manifest?.contracts?.mediaUnderstandingProviders?.[0];if(typeof n==`string`&&n.trim())return n.trim()}function z(){return _(d,p)}function B(){return _(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,m,`dark:border-edge`)}function V(e,t){if(!e||!t)return{apiKey:``,model:R[0].id};if(t===`alibaba`)return{apiKey:e.stt.alibaba?.apiKey??``,model:e.stt.alibaba?.model??`paraformer-v2`};if(t===`openai`)return{apiKey:e.stt.openai?.apiKey??``,model:e.stt.openai?.model??`whisper-1`};let n=e.stt.providers?.[t];return{apiKey:typeof n?.apiKey==`string`?n.apiKey:``,model:typeof n?.model==`string`?n.model:R[0].id}}function H({providerId:e,voiceSettings:t,mutateVoice:n}){let r=a(i(e=>e.language)),c=r.voiceSettings,l=r.extensionSttMedia,u={maskedHelp:c.apiKeyMaskedHelp,copy:c.apiKeyCopy,copied:c.apiKeyCopied,show:c.apiKeyShow,hide:c.apiKeyHide,notInConfigFile:c.apiKeyNotInConfigFile,loadFailed:c.apiKeyRevealFailed},{data:d}=s(o(`/api/voice/stt-providers`),x,{revalidateOnFocus:!1}),f=(0,j.useMemo)(()=>d?.providers.some(t=>t.id===e&&t.configured)??!1,[e,d]),m=(0,j.useMemo)(()=>V(t,e),[e,t]),h=(0,j.useRef)(!1),[g,v]=(0,j.useState)(null),[b,S]=(0,j.useState)(!1),[C,w]=(0,j.useState)(null),[T,O]=(0,j.useState)(!1),A=g??m,N=m,P=A.apiKey!==N.apiKey||A.model!==N.model,F=(0,j.useCallback)(async()=>{S(!0),w(null);try{let r=structuredClone(t);r.stt.enabled=!0,e===`alibaba`?(r.stt.provider=`alibaba`,r.stt.alibaba={...r.stt.alibaba,apiKey:A.apiKey,model:A.model}):e===`openai`?(r.stt.provider=`openai`,r.stt.openai={...r.stt.openai,apiKey:A.apiKey,model:A.model}):(r.stt.providers={...r.stt.providers??{},[e]:{...r.stt.providers?.[e]??{},apiKey:A.apiKey,model:A.model}},(!r.stt.provider||r.stt.provider===`alibaba`||r.stt.provider===`openai`)&&(r.stt.provider=e)),await E(r),await n(r,!1),h.current=!1,v(null),O(!0),window.setTimeout(()=>O(!1),2500)}catch(e){w(e instanceof Error?e.message:String(e))}finally{S(!1)}},[A.apiKey,A.model,n,e,t]),I=e===`groq`?R:[{id:A.model,name:A.model}];return(0,M.jsxs)(`div`,{className:`flex flex-col gap-4 rounded-xl border border-edge bg-surface-base p-4`,children:[(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:l.credentialsTitle}),(0,M.jsx)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:l.credentialsHint.replace(`{providerId}`,e)})]}),(0,M.jsx)(`span`,{className:_(`rounded-full px-2 py-0.5 text-xs font-medium`,f?`bg-emerald-500/10 text-emerald-700 dark:text-emerald-300`:`bg-amber-500/10 text-amber-800 dark:text-amber-200`),children:f?l.configured:l.notConfigured})]}),(0,M.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,M.jsxs)(`div`,{className:_(`flex flex-col gap-1.5`,p),children:[(0,M.jsx)(k,{children:c.stt.apiKey}),(0,M.jsx)(D,{kind:`stt`,providerId:e,fieldId:`ext-stt-${e}-api-key`,value:A.apiKey,onChange:e=>{h.current=!0,v(t=>({...t??m,apiKey:e})),w(null)},labels:u,placeholder:e===`groq`?`gsk_...`:`sk-...`}),(0,M.jsxs)(`p`,{className:`text-xs text-fg-subtle`,children:[c.stt.apiKeyDesc,e===`groq`?` (GROQ_API_KEY)`:``]})]}),(0,M.jsxs)(`div`,{className:_(`flex flex-col gap-1.5`,p),children:[(0,M.jsx)(k,{children:c.stt.model}),e===`groq`?(0,M.jsx)(`select`,{className:z(),value:A.model,onChange:e=>{h.current=!0,v(t=>({...t??m,model:e.target.value})),w(null)},children:I.map(e=>(0,M.jsx)(`option`,{value:e.id,children:e.name},e.id))}):(0,M.jsx)(`input`,{className:B(),value:A.model,onChange:e=>{h.current=!0,v(t=>({...t??m,model:e.target.value})),w(null)}})]})]}),(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[T?(0,M.jsx)(`span`,{className:`text-xs text-emerald-600 dark:text-emerald-400`,children:c.saved}):null,C?(0,M.jsx)(`span`,{className:`text-xs text-red-600 dark:text-red-400`,children:C}):null,(0,M.jsx)(y,{type:`button`,variant:`ghost`,className:`h-8 text-xs`,disabled:!P||b,onClick:()=>{h.current=!1,v(null),w(null)},children:c.discard}),(0,M.jsx)(y,{type:`button`,variant:`primary`,className:`h-8 text-xs`,disabled:!P||b,onClick:()=>void F(),children:b?c.saving:c.save})]})]})}function U(e){let t=(0,A.c)(13),{extensionId:n}=e,r=i(G),a=c(W),u;t[0]===n?u=t[1]:(u=()=>l(o(`/api/extensions/${encodeURIComponent(n)}`)),t[0]=n,t[1]=u);let{data:d,isLoading:f}=s(a&&n?`ext-stt-detail-${n}`:null,u),p;t[2]===d?p=t[3]:(p=ee(d),t[2]=d,t[3]=p);let m=p,g;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(g={revalidateOnFocus:!1},t[4]=g):g=t[4];let{data:_,mutate:v,isLoading:y}=s(a?`voice-settings-ext-stt`:null,w,g);if(!a)return null;if(f||y){let e;return t[5]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,M.jsxs)(`div`,{className:`flex items-center gap-2 py-6 text-sm text-fg-muted`,children:[(0,M.jsx)(h,{className:`size-4 animate-spin`}),`…`]}),t[5]=e):e=t[5],e}if(!m){let e=r===`zh`?`该扩展未声明 mediaUnderstandingProviders。`:`This extension does not declare mediaUnderstandingProviders.`,n;return t[6]===e?n=t[7]:(n=(0,M.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e}),t[6]=e,t[7]=n),n}if(!_)return null;let b=`${n}:${m}`,x;return t[8]!==v||t[9]!==m||t[10]!==b||t[11]!==_?(x=(0,M.jsx)(H,{providerId:m,voiceSettings:_,mutateVoice:v},b),t[8]=v,t[9]=m,t[10]=b,t[11]=_,t[12]=x):x=t[12],x}function W(e){return!!e.token}function G(e){return e.language}function K(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function q(e){let t=e[`x-order`];return typeof t==`number`&&!Number.isNaN(t)?t:999}function J(e){let t=e[`x-group`];return typeof t==`string`&&t.length>0?t:``}function Y(e){return e[`x-hidden`]===!0}function X(e){let t=e.properties;if(!K(t))return[];let n=[];for(let[e,r]of Object.entries(t))K(r)&&(Y(r)||n.push({key:e,sub:r,order:q(r),group:J(r),hidden:!1}));return n.sort((e,t)=>e.order-t.order||e.key.localeCompare(t.key)),n}function Z(e){let t=new Map;for(let n of e){let e=n.group;t.has(e)||t.set(e,[]),t.get(e).push(n)}return t}function te(e){let t=(0,A.c)(29),{name:n,s:r,value:i,onChange:a,disabled:o}=e,s=typeof r.description==`string`?r.description:void 0,c=(typeof r[`x-placeholder`]==`string`?r[`x-placeholder`]:null)||s,l=r.format;if(Array.isArray(r.enum)&&r.enum.every(re)){let e;t[0]===s?e=t[1]:(e=s?(0,M.jsx)(`label`,{className:`text-xs text-fg-muted`,children:s}):null,t[0]=s,t[1]=e);let c;t[2]===a?c=t[3]:(c=e=>a(e.target.value),t[2]=a,t[3]=c);let l;t[4]===r.enum?l=t[5]:(l=r.enum.map(ne),t[4]=r.enum,t[5]=l);let u;t[6]!==o||t[7]!==n||t[8]!==c||t[9]!==l||t[10]!==i?(u=(0,M.jsx)(`select`,{name:n,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2 text-sm text-fg`,value:i,disabled:o,onChange:c,children:l}),t[6]=o,t[7]=n,t[8]=c,t[9]=l,t[10]=i,t[11]=u):u=t[11];let d;return t[12]!==e||t[13]!==u?(d=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[e,u]}),t[12]=e,t[13]=u,t[14]=d):d=t[14],d}let u=l===`password`?`password`:`text`,d;t[15]===s?d=t[16]:(d=s?(0,M.jsx)(`label`,{className:`text-xs text-fg-muted`,children:s}):null,t[15]=s,t[16]=d);let f;t[17]===a?f=t[18]:(f=e=>a(e.target.value),t[17]=a,t[18]=f);let p;t[19]!==o||t[20]!==u||t[21]!==n||t[22]!==c||t[23]!==f||t[24]!==i?(p=(0,M.jsx)(`input`,{name:n,type:u,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg placeholder:text-fg-muted/70`,value:i,placeholder:c,disabled:o,onChange:f}),t[19]=o,t[20]=u,t[21]=n,t[22]=c,t[23]=f,t[24]=i,t[25]=p):p=t[25];let m;return t[26]!==d||t[27]!==p?(m=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[d,p]}),t[26]=d,t[27]=p,t[28]=m):m=t[28],m}function ne(e){return(0,M.jsx)(`option`,{value:e,children:e},e)}function re(e){return typeof e==`string`}function ie(e){let t=(0,A.c)(11),{s:n,value:r,onChange:i,disabled:a}=e,o=typeof n.description==`string`?n.description:void 0,s;t[0]===o?s=t[1]:(s=o?(0,M.jsx)(`label`,{className:`text-xs text-fg-muted`,children:o}):null,t[0]=o,t[1]=s);let c=Number.isFinite(r)?r:0,l;t[2]===i?l=t[3]:(l=e=>i(Number(e.target.value)),t[2]=i,t[3]=l);let u;t[4]!==a||t[5]!==c||t[6]!==l?(u=(0,M.jsx)(`input`,{type:`number`,className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm text-fg`,value:c,disabled:a,onChange:l}),t[4]=a,t[5]=c,t[6]=l,t[7]=u):u=t[7];let d;return t[8]!==s||t[9]!==u?(d=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[s,u]}),t[8]=s,t[9]=u,t[10]=d):d=t[10],d}function ae(e){let t=(0,A.c)(11),{s:n,value:r,onChange:i,disabled:a}=e,o=(typeof n.description==`string`?n.description:void 0)??(typeof n.title==`string`&&n.title.length>0?n.title:`Enable`),s;t[0]===i?s=t[1]:(s=e=>i(e.target.checked),t[0]=i,t[1]=s);let c;t[2]!==a||t[3]!==s||t[4]!==r?(c=(0,M.jsx)(`input`,{type:`checkbox`,className:`size-4 rounded border border-edge`,checked:r,disabled:a,onChange:s}),t[2]=a,t[3]=s,t[4]=r,t[5]=c):c=t[5];let l;t[6]===o?l=t[7]:(l=(0,M.jsx)(`span`,{children:o}),t[6]=o,t[7]=l);let u;return t[8]!==c||t[9]!==l?(u=(0,M.jsxs)(`label`,{className:`flex items-center gap-2 text-sm text-fg`,children:[c,l]}),t[8]=c,t[9]=l,t[10]=u):u=t[10],u}function oe(e){let t=(0,A.c)(21),{s:n,value:r,onChange:i,disabled:a}=e,o=typeof n.description==`string`?n.description:void 0,s=n.items;if(!(K(s)&&s.type===`string`)){let e;return t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=(0,M.jsx)(`p`,{className:`text-xs text-fg-muted`,children:`Unsupported array type`}),t[0]=e):e=t[0],e}let c;t[1]!==i||t[2]!==r?(c=e=>{let t=e.trim();!t||r.includes(t)||i([...r,t])},t[1]=i,t[2]=r,t[3]=c):c=t[3];let l=c,u;t[4]===o?u=t[5]:(u=o?(0,M.jsx)(`label`,{className:`text-xs text-fg-muted`,children:o}):null,t[4]=o,t[5]=u);let d;t[6]!==a||t[7]!==i||t[8]!==r?(d=r.map(e=>(0,M.jsxs)(`span`,{className:`inline-flex items-center gap-1 rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-sm`,children:[e,(0,M.jsx)(`button`,{type:`button`,className:`text-fg-muted hover:text-fg`,disabled:a,onClick:()=>i(r.filter(t=>t!==e)),children:`×`})]},e)),t[6]=a,t[7]=i,t[8]=r,t[9]=d):d=t[9];let f;t[10]===d?f=t[11]:(f=(0,M.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:d}),t[10]=d,t[11]=f);let p;t[12]===l?p=t[13]:(p=e=>{e.key===`Enter`&&(e.preventDefault(),l(e.target.value),e.target.value=``)},t[12]=l,t[13]=p);let m;t[14]!==a||t[15]!==p?(m=(0,M.jsx)(`input`,{className:`ui-input h-9 rounded-md border border-edge bg-surface-base px-2.5 text-sm`,disabled:a,placeholder:`Add and press Enter`,onKeyDown:p}),t[14]=a,t[15]=p,t[16]=m):m=t[16];let h;return t[17]!==u||t[18]!==f||t[19]!==m?(h=(0,M.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[u,f,m]}),t[17]=u,t[18]=f,t[19]=m,t[20]=h):h=t[20],h}function se(e){let t=(0,A.c)(48),{k:n,sub:r,value:i,onValue:a,disabled:o}=e,s=r.type,c=(typeof r.title==`string`&&r.title.length>0?r.title:null)??n;if(s===`boolean`){let e;t[0]===c?e=t[1]:(e=(0,M.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:c}),t[0]=c,t[1]=e);let n=i===!0,s;t[2]===a?s=t[3]:(s=e=>a(e),t[2]=a,t[3]=s);let l;t[4]!==o||t[5]!==r||t[6]!==n||t[7]!==s?(l=(0,M.jsx)(ae,{s:r,value:n,disabled:o,onChange:s}),t[4]=o,t[5]=r,t[6]=n,t[7]=s,t[8]=l):l=t[8];let u;return t[9]!==e||t[10]!==l?(u=(0,M.jsxs)(`div`,{className:`space-y-1.5`,children:[e,l]}),t[9]=e,t[10]=l,t[11]=u):u=t[11],u}if(s===`number`||s===`integer`){let e;t[12]===c?e=t[13]:(e=(0,M.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:c}),t[12]=c,t[13]=e);let n=typeof i==`number`?i:0,s;t[14]!==o||t[15]!==a||t[16]!==r||t[17]!==n?(s=(0,M.jsx)(ie,{s:r,value:n,disabled:o,onChange:a}),t[14]=o,t[15]=a,t[16]=r,t[17]=n,t[18]=s):s=t[18];let l;return t[19]!==e||t[20]!==s?(l=(0,M.jsxs)(`div`,{className:`space-y-1.5`,children:[e,s]}),t[19]=e,t[20]=s,t[21]=l):l=t[21],l}if(s===`string`){let e;t[22]===c?e=t[23]:(e=(0,M.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:c}),t[22]=c,t[23]=e);let s=typeof i==`string`?i:``,l;t[24]!==o||t[25]!==n||t[26]!==a||t[27]!==r||t[28]!==s?(l=(0,M.jsx)(te,{name:n,s:r,value:s,disabled:o,onChange:a}),t[24]=o,t[25]=n,t[26]=a,t[27]=r,t[28]=s,t[29]=l):l=t[29];let u;return t[30]!==e||t[31]!==l?(u=(0,M.jsxs)(`div`,{className:`space-y-1.5`,children:[e,l]}),t[30]=e,t[31]=l,t[32]=u):u=t[32],u}if(s===`array`){let e=r.items;if(K(e)&&e.type===`string`){let e;t[33]===c?e=t[34]:(e=(0,M.jsx)(`p`,{className:`text-sm font-medium text-fg`,children:c}),t[33]=c,t[34]=e);let n;t[35]===i?n=t[36]:(n=Array.isArray(i)&&i.every(ce)?i:[],t[35]=i,t[36]=n);let s;t[37]!==o||t[38]!==a||t[39]!==r||t[40]!==n?(s=(0,M.jsx)(oe,{s:r,value:n,disabled:o,onChange:a}),t[37]=o,t[38]=a,t[39]=r,t[40]=n,t[41]=s):s=t[41];let l;return t[42]!==e||t[43]!==s?(l=(0,M.jsxs)(`div`,{className:`space-y-1.5`,children:[e,s]}),t[42]=e,t[43]=s,t[44]=l):l=t[44],l}}let l=typeof s==`string`?` (${s})`:``,u;return t[45]!==l||t[46]!==c?(u=(0,M.jsxs)(`p`,{className:`text-xs text-fg-muted`,children:[c,`: unsupported field type`,l]}),t[45]=l,t[46]=c,t[47]=u):u=t[47],u}function ce(e){return typeof e==`string`}function le(e){let t=(0,A.c)(26),{schema:n,values:r,onChange:i,disabled:a,className:o}=e,s=a===void 0?!1:a,c;bb0:{if(n.type!==`object`){let e;t[0]===Symbol.for(`react.memo_cache_sentinel`)?(e=[],t[0]=e):e=t[0],c=e;break bb0}let e;t[1]===n?e=t[2]:(e=X(n),t[1]=n,t[2]=e),c=e}let l=c,u;bb1:{if(l.length===0){let e;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(e=new Map,t[3]=e):e=t[3],u=e;break bb1}let e;t[4]===l?e=t[5]:(e=Z(l),t[4]=l,t[5]=e),u=e}let d=u,f;t[6]!==i||t[7]!==r?(f=(e,t)=>{i({...r,[e]:t})},t[6]=i,t[7]=r,t[8]=f):f=t[8];let p=f;if(n.type!==`object`||!K(n.properties)||l.length===0)return null;let m,h;if(t[9]!==o||t[10]!==s||t[11]!==d||t[12]!==p||t[13]!==r){let e=Array.from(d.keys()).sort(ue);t[16]===o?m=t[17]:(m=_(`flex flex-col gap-4`,o),t[16]=o,t[17]=m);let n;t[18]!==s||t[19]!==d||t[20]!==p||t[21]!==r?(n=e=>{let t=(d.get(e)??[]).map(e=>(0,M.jsx)(se,{k:e.key,sub:e.sub,value:r[e.key],onValue:t=>p(e.key,t),disabled:s},e.key));return e===``?(0,M.jsx)(`div`,{children:t},`default`):(0,M.jsxs)(`details`,{className:`group rounded-lg border border-edge bg-surface-panel/40 open:bg-surface-base`,open:!0,children:[(0,M.jsx)(`summary`,{className:`cursor-pointer select-none px-3 py-2 text-sm font-medium text-fg group-open:rounded-b-none`,children:e}),(0,M.jsx)(`div`,{className:`space-y-4 border-t border-edge p-3`,children:t})]},e)},t[18]=s,t[19]=d,t[20]=p,t[21]=r,t[22]=n):n=t[22],h=e.map(n),t[9]=o,t[10]=s,t[11]=d,t[12]=p,t[13]=r,t[14]=m,t[15]=h}else m=t[14],h=t[15];let g;return t[23]!==m||t[24]!==h?(g=(0,M.jsx)(`div`,{className:m,children:h}),t[23]=m,t[24]=h,t[25]=g):g=t[25],g}function ue(e,t){return e===``?-1:t===``?1:e.localeCompare(t)}function Q(e){let t={};if(e.type!==`object`||!K(e.properties))return t;for(let[n,r]of Object.entries(e.properties))K(r)&&Object.prototype.hasOwnProperty.call(r,`default`)&&(t[n]=r.default);return t}function de(e,t){switch(t.type){case`sync`:return{...e,localValues:t.value,isDirty:!1,saveError:null};case`change`:return{...e,localValues:t.value,isDirty:!0,saveError:null,saveSuccess:!1};case`discard`:return{...e,localValues:t.value,isDirty:!1,saveError:null};case`reset-defaults`:return{...e,localValues:t.value,isDirty:!0,saveError:null,saveSuccess:!1};case`save-start`:return{...e,saving:!0,saveError:null};case`save-success`:return{...e,localValues:t.value,isDirty:!1,saving:!1,saveSuccess:!0,saveError:null};case`save-error`:return{...e,saving:!1,saveError:t.message}}}function fe({extensionId:e}){let t=a(i(e=>e.language)).agentSettings,n=c(e=>!!e.token),{data:r,error:d}=s(n&&e?`ext-detail-${e}`:null,()=>l(o(`/api/extensions/${encodeURIComponent(e)}`))),{data:f,mutate:p,error:m}=s(n&&e?`ext-cfg-${e}`:null,()=>l(o(`/api/extensions/${encodeURIComponent(e)}/config`))),h=r?.manifest?.configSchema,g=(0,j.useMemo)(()=>h&&h.type===`object`?Q(h):{},[h]),_=(0,j.useMemo)(()=>({...g,...f??{}}),[g,f]),[v,b]=(0,j.useReducer)(de,{localValues:{},isDirty:!1,saving:!1,saveError:null,saveSuccess:!1}),[x,S]=(0,j.useState)(!1),C=(0,j.useRef)(!1),w=(0,j.useRef)(_);!C.current&&w.current!==_&&(w.current=_,b({type:`sync`,value:_}));let T=(0,j.useCallback)(e=>{C.current=!0,b({type:`change`,value:e})},[]),E=(0,j.useCallback)(()=>{C.current=!1,b({type:`discard`,value:_})},[_]),D=(0,j.useCallback)(()=>{!h||h.type!==`object`||(C.current=!0,b({type:`reset-defaults`,value:{...Q(h)}}))},[h]),O=(0,j.useCallback)(async()=>{if(e){b({type:`save-start`});try{let t=await u(o(`/api/extensions/${encodeURIComponent(e)}/config`),{method:`PATCH`,body:JSON.stringify(v.localValues)});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error?.message??t.statusText)}await p(v.localValues,!1),C.current=!1,b({type:`save-success`,value:v.localValues}),S(!0),window.setTimeout(()=>S(!1),3e3)}catch(e){b({type:`save-error`,message:e instanceof Error?e.message:String(e)})}}},[v.localValues,e,p]);if(!n)return null;if(d||m){let e=d??m;return(0,M.jsxs)(`p`,{className:`text-sm text-fg-muted`,children:[`Could not load extension settings: `,e instanceof Error?e.message:String(e)]})}return!h||h.type!==`object`?null:(0,M.jsxs)(`div`,{className:`mb-6 flex flex-col gap-3 rounded-xl border border-edge bg-surface-base p-4`,children:[(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,M.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:`Configuration`}),(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[x?(0,M.jsx)(`span`,{className:`text-xs text-emerald-600 dark:text-emerald-400`,children:t.saved}):null,v.saveError?(0,M.jsx)(`span`,{className:`text-xs text-red-600 dark:text-red-400`,children:v.saveError}):null,(0,M.jsx)(y,{type:`button`,variant:`ghost`,className:`h-8 text-xs`,disabled:!v.isDirty,onClick:E,children:t.discard}),(0,M.jsx)(y,{type:`button`,variant:`ghost`,className:`h-8 text-xs`,onClick:D,children:`Reset to defaults`}),(0,M.jsx)(y,{type:`button`,variant:`primary`,className:`h-8 text-xs`,disabled:!v.isDirty||v.saving,onClick:()=>void O(),children:v.saving?t.saving:t.save})]})]}),(0,M.jsx)(le,{schema:h,values:v.localValues,onChange:T,disabled:v.saving})]})}function pe(){let e=(0,A.c)(47),t=i(me),n;e[0]===t?n=e[1]:(n=a(t),e[0]=t,e[1]=n);let r=n,o=r.extensionImageGen,s=r.extensionSttMedia,{extensionId:c,panelId:l}=b(),u=f();if(!c){let t;return e[2]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,M.jsx)($,{message:`No extension ID provided.`}),e[2]=t):t=e[2],t}let d,p,m;if(e[3]!==c||e[4]!==u||e[5]!==l){m=Symbol.for(`react.early_return_sentinel`);bb0:{let t;if(e[9]===c?t=e[10]:(t=e=>e.id===c,e[9]=c,e[10]=t),d=u.find(t),!d){let t=`Extension "${c}" not found or is not available in this workspace.`,n;e[11]===t?n=e[12]:(n=(0,M.jsx)($,{message:t}),e[11]=t,e[12]=n),m=n;break bb0}let n=d.ui?.contributions?.settingsPanels;p=l?n?.find(e=>e.id===l||e.id===`${c}.${l}`):n?.[0]}e[3]=c,e[4]=u,e[5]=l,e[6]=d,e[7]=p,e[8]=m}else d=e[6],p=e[7],m=e[8];if(m!==Symbol.for(`react.early_return_sentinel`))return m;let h=p,_=!!(h&&d.ui),y=!!d.hasConfigSchema,x=d.kind===`image-generation`,S=d.kind===`media-provider`;if(!y&&!_&&!(x||S)){let t=`Extension "${c}" has no settings panels or config schema.`,n;return e[13]===t?n=e[14]:(n=(0,M.jsx)($,{message:t}),e[13]=t,e[14]=n),n}let C=h?.title??`${d.name} Settings`,w;e[15]===C?w=e[16]:(w=(0,M.jsx)(`h1`,{className:`text-lg font-semibold text-fg`,children:C}),e[15]=C,e[16]=w);let T;e[17]!==x||e[18]!==r.imageModelsSettings||e[19]!==o?(T=x?(0,M.jsxs)(`div`,{className:`flex flex-col gap-2 rounded-lg border border-edge-subtle bg-surface-base px-4 py-3 text-sm`,children:[(0,M.jsx)(`p`,{className:`leading-relaxed text-fg-muted`,children:o.banner}),(0,M.jsx)(v,{to:`/settings/image-models`,className:`w-fit font-medium text-accent hover:underline`,title:r.imageModelsSettings.imageModelsLinkTitle,children:o.openImageModels})]}):null,e[17]=x,e[18]=r.imageModelsSettings,e[19]=o,e[20]=T):T=e[20];let E;e[21]!==c||e[22]!==x?(E=x?(0,M.jsx)(F,{extensionId:c}):null,e[21]=c,e[22]=x,e[23]=E):E=e[23];let D;e[24]!==S||e[25]!==s?(D=S?(0,M.jsxs)(`div`,{className:`flex flex-col gap-2 rounded-lg border border-edge-subtle bg-surface-base px-4 py-3 text-sm`,children:[(0,M.jsx)(`p`,{className:`leading-relaxed text-fg-muted`,children:s.banner}),(0,M.jsx)(v,{to:`/settings/voice`,className:`w-fit font-medium text-accent hover:underline`,children:s.openVoice})]}):null,e[24]=S,e[25]=s,e[26]=D):D=e[26];let O;e[27]!==c||e[28]!==S?(O=S?(0,M.jsx)(U,{extensionId:c}):null,e[27]=c,e[28]=S,e[29]=O):O=e[29];let k;e[30]!==c||e[31]!==y?(k=y?(0,M.jsx)(fe,{extensionId:c}):null,e[30]=c,e[31]=y,e[32]=k):k=e[32];let j;e[33]!==d.name||e[34]!==d.ui||e[35]!==c||e[36]!==_||e[37]!==h?(j=_&&h&&d.ui?(0,M.jsx)(`div`,{className:`overflow-hidden rounded-xl border border-edge bg-surface-base`,children:(0,M.jsx)(g,{extensionId:c,extensionName:d.name,entrypoint:h.entrypoint,permissions:d.ui?.permissions,title:h.title,className:`w-full`,minHeight:120,maxHeight:2e3})}):null,e[33]=d.name,e[34]=d.ui,e[35]=c,e[36]=_,e[37]=h,e[38]=j):j=e[38];let N;return e[39]!==w||e[40]!==T||e[41]!==E||e[42]!==D||e[43]!==O||e[44]!==k||e[45]!==j?(N=(0,M.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:[w,T,E,D,O,k,j]}),e[39]=w,e[40]=T,e[41]=E,e[42]=D,e[43]=O,e[44]=k,e[45]=j,e[46]=N):N=e[46],N}function me(e){return e.language}function $(e){let t=(0,A.c)(2),{message:n}=e,r;return t[0]===n?r=t[1]:(r=(0,M.jsx)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:(0,M.jsx)(`p`,{className:`text-sm text-fg-muted`,children:n})}),t[0]=n,t[1]=r),r}export{pe as ExtensionSettingsPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"./vendor-react-BOUWij0V.js";import{nr as n,qr as r,zt as i}from"./index-D4vM3-P7.js";var a=e(),o=t();function s(){return`rounded-2xl bg-surface-base px-4 py-5 sm:px-5`}function c(e){let t=(0,a.c)(5),{children:r,className:i}=e,c;t[0]===i?c=t[1]:(c=n(s(),i),t[0]=i,t[1]=c);let l;return t[2]!==r||t[3]!==c?(l=(0,o.jsx)(`section`,{className:c,children:r}),t[2]=r,t[3]=c,t[4]=l):l=t[4],l}var l=`flex size-9 shrink-0 items-center justify-center rounded-lg bg-surface-hover/90 text-fg-muted transition-colors dark:bg-surface-hover/70`;function u(e){let t=(0,a.c)(26),{icon:s,title:c,subtitle:u,trailing:d,className:f,iconInteractive:p,iconLeading:m}=e,h;t[0]===s?h=t[1]:(h=(0,o.jsx)(s,{className:`size-4`,strokeWidth:1.75,"aria-hidden":!0}),t[0]=s,t[1]=h);let g=m??h,_;t[2]===m?_=t[3]:(_=m?n(`flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-surface-panel p-0 ring-1 ring-inset ring-edge-subtle transition-[box-shadow] hover:ring-accent/40 dark:ring-edge-subtle`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-base`,i.press):n(l,`hover:text-fg`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-base`,i.press),t[2]=m,t[3]=_);let v=_,y=!!(p&&m),b;t[4]===f?b=t[5]:(b=n(`mb-5 flex items-start gap-3`,f),t[4]=f,t[5]=b);let x;t[6]!==p||t[7]!==m||t[8]!==g||t[9]!==v||t[10]!==y?(x=p?y?(0,o.jsxs)(`span`,{className:`relative shrink-0`,children:[(0,o.jsx)(`button`,{type:`button`,id:p.id,onClick:p.onClick,"aria-label":p.ariaLabel,className:v,children:g}),(0,o.jsx)(`span`,{className:`pointer-events-none absolute -bottom-0.5 -right-0.5 flex size-4 items-center justify-center rounded-md border border-edge bg-surface-panel text-fg-muted shadow-sm dark:border-edge dark:bg-surface-base`,"aria-hidden":!0,children:(0,o.jsx)(r,{className:`size-2.5`,strokeWidth:2.25})})]}):(0,o.jsx)(`button`,{type:`button`,id:p.id,onClick:p.onClick,"aria-label":p.ariaLabel,className:v,children:g}):(0,o.jsx)(`div`,{className:n(m?`flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-surface-panel ring-1 ring-inset ring-edge-subtle dark:ring-edge-subtle`:l),"aria-hidden":!m,children:g}),t[6]=p,t[7]=m,t[8]=g,t[9]=v,t[10]=y,t[11]=x):x=t[11];let S;t[12]===c?S=t[13]:(S=(0,o.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:c}),t[12]=c,t[13]=S);let C;t[14]===u?C=t[15]:(C=u?(0,o.jsx)(`p`,{className:`mt-0.5 text-xs text-fg-muted`,children:u}):null,t[14]=u,t[15]=C);let w;t[16]!==S||t[17]!==C?(w=(0,o.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[S,C]}),t[16]=S,t[17]=C,t[18]=w):w=t[18];let T;t[19]===d?T=t[20]:(T=d?(0,o.jsx)(`div`,{className:`shrink-0`,children:d}):null,t[19]=d,t[20]=T);let E;return t[21]!==b||t[22]!==x||t[23]!==w||t[24]!==T?(E=(0,o.jsxs)(`div`,{className:b,children:[x,w,T]}),t[21]=b,t[22]=x,t[23]=w,t[24]=T,t[25]=E):E=t[25],E}export{u as n,s as r,c as t};
|