@voybio/ace-swarm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +109 -0
- package/LICENSE +186 -0
- package/README.md +229 -0
- package/assets/.agents/ACE/ACE-Init/AGENTS.md +210 -0
- package/assets/.agents/ACE/ACE-Init/instructions.md +118 -0
- package/assets/.agents/ACE/ACE_coders/AGENTS.md +154 -0
- package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +216 -0
- package/assets/.agents/ACE/AGENT_REGISTRY.md +70 -0
- package/assets/.agents/ACE/AGENT_REGISTRY_7.md +9 -0
- package/assets/.agents/ACE/DIRECTIVE_KERNEL.md +234 -0
- package/assets/.agents/ACE/UI/AGENTS.md +115 -0
- package/assets/.agents/ACE/UI/instructions.md +178 -0
- package/assets/.agents/ACE/VOS/ACE_VOS_MISSING_INFO_MATRIX.md +42 -0
- package/assets/.agents/ACE/VOS/AGENTS.md +72 -0
- package/assets/.agents/ACE/VOS/instructions.md +211 -0
- package/assets/.agents/ACE/agent-astgrep/AGENTS.md +123 -0
- package/assets/.agents/ACE/agent-astgrep/instructions.md +91 -0
- package/assets/.agents/ACE/agent-builder/AGENTS.md +172 -0
- package/assets/.agents/ACE/agent-builder/instructions.md +137 -0
- package/assets/.agents/ACE/agent-docs/AGENTS.md +159 -0
- package/assets/.agents/ACE/agent-docs/instructions.md +133 -0
- package/assets/.agents/ACE/agent-eval/AGENTS.md +46 -0
- package/assets/.agents/ACE/agent-eval/instructions.md +56 -0
- package/assets/.agents/ACE/agent-memory/AGENTS.md +49 -0
- package/assets/.agents/ACE/agent-memory/instructions.md +50 -0
- package/assets/.agents/ACE/agent-observability/AGENTS.md +46 -0
- package/assets/.agents/ACE/agent-observability/instructions.md +50 -0
- package/assets/.agents/ACE/agent-ops/AGENTS.md +201 -0
- package/assets/.agents/ACE/agent-ops/instructions.md +136 -0
- package/assets/.agents/ACE/agent-qa/AGENTS.md +189 -0
- package/assets/.agents/ACE/agent-qa/instructions.md +121 -0
- package/assets/.agents/ACE/agent-release/AGENTS.md +48 -0
- package/assets/.agents/ACE/agent-release/instructions.md +49 -0
- package/assets/.agents/ACE/agent-research/AGENTS.md +160 -0
- package/assets/.agents/ACE/agent-research/instructions.md +118 -0
- package/assets/.agents/ACE/agent-security/AGENTS.md +48 -0
- package/assets/.agents/ACE/agent-security/instructions.md +50 -0
- package/assets/.agents/ACE/agent-skeptic/AGENTS.md +178 -0
- package/assets/.agents/ACE/agent-skeptic/instructions.md +196 -0
- package/assets/.agents/ACE/agent-spec/AGENTS.md +169 -0
- package/assets/.agents/ACE/agent-spec/instructions.md +116 -0
- package/assets/.agents/ACE/orchestrator/AGENTS.md +365 -0
- package/assets/.agents/ACE/orchestrator/instructions.md +231 -0
- package/assets/.agents/skills/ace-orchestrator/SKILL.md +63 -0
- package/assets/.agents/skills/ace-orchestrator/references/engineering-bootstrap-playbook.md +360 -0
- package/assets/.agents/skills/astgrep-index/SKILL.md +58 -0
- package/assets/.agents/skills/codemunch/SKILL.md +65 -0
- package/assets/.agents/skills/codemunch/references/ast-driven-protocol.md +543 -0
- package/assets/.agents/skills/codesnipe/SKILL.md +64 -0
- package/assets/.agents/skills/codesnipe/references/dual-codebase-playbook.md +671 -0
- package/assets/.agents/skills/eval-harness/SKILL.md +203 -0
- package/assets/.agents/skills/handoff-lint/SKILL.md +164 -0
- package/assets/.agents/skills/incident-commander/SKILL.md +174 -0
- package/assets/.agents/skills/landing-review-watcher/SKILL.md +68 -0
- package/assets/.agents/skills/memory-curator/SKILL.md +179 -0
- package/assets/.agents/skills/problem-triage/SKILL.md +57 -0
- package/assets/.agents/skills/problem-triage/agents/openai.yaml +3 -0
- package/assets/.agents/skills/release-sentry/SKILL.md +189 -0
- package/assets/.agents/skills/risk-quant/SKILL.md +190 -0
- package/assets/.agents/skills/schema-forge/SKILL.md +174 -0
- package/assets/.agents/skills/skill-auditor/SKILL.md +52 -0
- package/assets/.agents/skills/state-auditor/SKILL.md +182 -0
- package/assets/.github/hooks/ace-copilot.json +68 -0
- package/assets/agent-state/ACE_WORKFLOW.md +131 -0
- package/assets/agent-state/ARTIFACT_MANIFEST.json +5 -0
- package/assets/agent-state/AST_GREP_COMMANDS.md +121 -0
- package/assets/agent-state/AST_GREP_INDEX.json +13 -0
- package/assets/agent-state/AST_GREP_INDEX.md +15 -0
- package/assets/agent-state/DECISIONS.md +7 -0
- package/assets/agent-state/EVIDENCE_LOG.md +7 -0
- package/assets/agent-state/HANDOFF.json +24 -0
- package/assets/agent-state/INTERFACE_REGISTRY.md +75 -0
- package/assets/agent-state/MODULES/gates/gate-autonomy.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-completeness.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-correctness.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-evaluation.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-operability.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-security.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-typescript-public-surface.json +7 -0
- package/assets/agent-state/MODULES/registry.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-astgrep.json +49 -0
- package/assets/agent-state/MODULES/roles/capability-build.json +39 -0
- package/assets/agent-state/MODULES/roles/capability-docs.json +38 -0
- package/assets/agent-state/MODULES/roles/capability-eval.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-memory.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-observability.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-ops.json +45 -0
- package/assets/agent-state/MODULES/roles/capability-qa.json +40 -0
- package/assets/agent-state/MODULES/roles/capability-release.json +21 -0
- package/assets/agent-state/MODULES/roles/capability-research.json +44 -0
- package/assets/agent-state/MODULES/roles/capability-security.json +21 -0
- package/assets/agent-state/MODULES/roles/capability-skeptic.json +48 -0
- package/assets/agent-state/MODULES/roles/capability-spec.json +42 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +289 -0
- package/assets/agent-state/MODULES/schemas/ARTIFACT_MANIFEST.schema.json +185 -0
- package/assets/agent-state/MODULES/schemas/HANDOFF.agent-state.schema.json +124 -0
- package/assets/agent-state/MODULES/schemas/HANDOFF.schema.json +55 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +290 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +144 -0
- package/assets/agent-state/MODULES/schemas/STATUS_EVENT.schema.json +84 -0
- package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +138 -0
- package/assets/agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json +134 -0
- package/assets/agent-state/MODULES/schemas/VERICIFY_BRIDGE_SNAPSHOT.schema.json +157 -0
- package/assets/agent-state/MODULES/schemas/VERICIFY_PROCESS_POST_LOG.schema.json +93 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +133 -0
- package/assets/agent-state/PROVENANCE_LOG.md +28 -0
- package/assets/agent-state/QUALITY_GATES.md +15 -0
- package/assets/agent-state/RISKS.md +8 -0
- package/assets/agent-state/SCOPE.md +20 -0
- package/assets/agent-state/SKILL_CATALOG.md +48 -0
- package/assets/agent-state/STATUS.md +8 -0
- package/assets/agent-state/STATUS_EVENTS.ndjson +1 -0
- package/assets/agent-state/TASK.md +18 -0
- package/assets/agent-state/TEAL_CONFIG.md +117 -0
- package/assets/agent-state/handoff-registry.json +5 -0
- package/assets/agent-state/index-fingerprints.json +7 -0
- package/assets/agent-state/index.json +32 -0
- package/assets/agent-state/run-ledger.json +5 -0
- package/assets/agent-state/runtime-executor-sessions.json +5 -0
- package/assets/agent-state/runtime-tool-specs.json +5 -0
- package/assets/agent-state/runtime-workspaces.json +5 -0
- package/assets/agent-state/todo-state.json +7 -0
- package/assets/agent-state/tracker-snapshot.json +7 -0
- package/assets/agent-state/vericify/ace-bridge.json +60 -0
- package/assets/agent-state/vericify/process-posts.json +5 -0
- package/assets/instructions/ACE.instructions.md +187 -0
- package/assets/instructions/ACE_Coder.instructions.md +146 -0
- package/assets/instructions/ACE_UI.instructions.md +178 -0
- package/assets/instructions/ACE_VOS.instructions.md +211 -0
- package/assets/scripts/ace-hook-dispatch.mjs +538 -0
- package/assets/scripts/bootstrap-workspace.sh +27 -0
- package/assets/scripts/copilot-hook-dispatch.mjs +3 -0
- package/assets/scripts/eval-harness.sh +68 -0
- package/assets/scripts/render-mcp-configs.sh +396 -0
- package/assets/tasks/README.md +48 -0
- package/assets/tasks/SWARM_HANDOFF.example.json +53 -0
- package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +55 -0
- package/assets/tasks/SWARM_HANDOFF.example_vos_to_ui.json +55 -0
- package/assets/tasks/SWARM_HANDOFF.template.json +52 -0
- package/assets/tasks/cli_work_split.md +22 -0
- package/assets/tasks/lessons.md +17 -0
- package/assets/tasks/role_tasks.md +206 -0
- package/assets/tasks/todo.md +23 -0
- package/dist/ace-autonomy.d.ts +137 -0
- package/dist/ace-autonomy.js +472 -0
- package/dist/ace-context.d.ts +29 -0
- package/dist/ace-context.js +240 -0
- package/dist/ace-internal-tools.d.ts +8 -0
- package/dist/ace-internal-tools.js +76 -0
- package/dist/ace-server-instructions.d.ts +12 -0
- package/dist/ace-server-instructions.js +324 -0
- package/dist/agent-runtime/role-adapters.d.ts +29 -0
- package/dist/agent-runtime/role-adapters.js +573 -0
- package/dist/astgrep-index.d.ts +24 -0
- package/dist/astgrep-index.js +476 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +591 -0
- package/dist/git-ops.d.ts +53 -0
- package/dist/git-ops.js +238 -0
- package/dist/handoff-registry.d.ts +71 -0
- package/dist/handoff-registry.js +422 -0
- package/dist/helpers.d.ts +126 -0
- package/dist/helpers.js +1687 -0
- package/dist/index-store.d.ts +51 -0
- package/dist/index-store.js +328 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/internal-tool-runtime.d.ts +21 -0
- package/dist/internal-tool-runtime.js +136 -0
- package/dist/job-scheduler.d.ts +175 -0
- package/dist/job-scheduler.js +1217 -0
- package/dist/kanban.d.ts +27 -0
- package/dist/kanban.js +339 -0
- package/dist/local-model-runtime.d.ts +40 -0
- package/dist/local-model-runtime.js +174 -0
- package/dist/model-bridge.d.ts +54 -0
- package/dist/model-bridge.js +587 -0
- package/dist/orchestrator-supervisor.d.ts +100 -0
- package/dist/orchestrator-supervisor.js +399 -0
- package/dist/problem-triage.d.ts +23 -0
- package/dist/problem-triage.js +448 -0
- package/dist/prompts.d.ts +7 -0
- package/dist/prompts.js +628 -0
- package/dist/public-surface.d.ts +30 -0
- package/dist/public-surface.js +316 -0
- package/dist/resources.d.ts +7 -0
- package/dist/resources.js +545 -0
- package/dist/run-ledger.d.ts +36 -0
- package/dist/run-ledger.js +257 -0
- package/dist/runtime-command.d.ts +18 -0
- package/dist/runtime-command.js +76 -0
- package/dist/runtime-executor.d.ts +104 -0
- package/dist/runtime-executor.js +985 -0
- package/dist/runtime-profile.d.ts +116 -0
- package/dist/runtime-profile.js +532 -0
- package/dist/runtime-tool-specs.d.ts +68 -0
- package/dist/runtime-tool-specs.js +527 -0
- package/dist/safe-edit.d.ts +52 -0
- package/dist/safe-edit.js +255 -0
- package/dist/schemas.d.ts +44 -0
- package/dist/schemas.js +830 -0
- package/dist/semantic-cache.d.ts +147 -0
- package/dist/semantic-cache.js +552 -0
- package/dist/semantic-hash.d.ts +83 -0
- package/dist/semantic-hash.js +346 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +46 -0
- package/dist/shared.d.ts +136 -0
- package/dist/shared.js +269 -0
- package/dist/skill-auditor.d.ts +26 -0
- package/dist/skill-auditor.js +184 -0
- package/dist/skill-catalog.d.ts +60 -0
- package/dist/skill-catalog.js +305 -0
- package/dist/status-events.d.ts +40 -0
- package/dist/status-events.js +269 -0
- package/dist/store/ace-packed-store.d.ts +69 -0
- package/dist/store/ace-packed-store.js +434 -0
- package/dist/store/bootstrap-store.d.ts +46 -0
- package/dist/store/bootstrap-store.js +242 -0
- package/dist/store/catalog-builder.d.ts +21 -0
- package/dist/store/catalog-builder.js +68 -0
- package/dist/store/importer.d.ts +19 -0
- package/dist/store/importer.js +157 -0
- package/dist/store/knowledge-bake.d.ts +59 -0
- package/dist/store/knowledge-bake.js +339 -0
- package/dist/store/materializers/hook-context-materializer.d.ts +25 -0
- package/dist/store/materializers/hook-context-materializer.js +100 -0
- package/dist/store/materializers/host-file-materializer.d.ts +37 -0
- package/dist/store/materializers/host-file-materializer.js +271 -0
- package/dist/store/materializers/todo-syncer.d.ts +30 -0
- package/dist/store/materializers/todo-syncer.js +140 -0
- package/dist/store/materializers/vericify-projector.d.ts +38 -0
- package/dist/store/materializers/vericify-projector.js +239 -0
- package/dist/store/repositories/discovery-repository.d.ts +24 -0
- package/dist/store/repositories/discovery-repository.js +58 -0
- package/dist/store/repositories/handoff-repository.d.ts +31 -0
- package/dist/store/repositories/handoff-repository.js +67 -0
- package/dist/store/repositories/ledger-repository.d.ts +26 -0
- package/dist/store/repositories/ledger-repository.js +49 -0
- package/dist/store/repositories/runtime-kv-repository.d.ts +16 -0
- package/dist/store/repositories/runtime-kv-repository.js +36 -0
- package/dist/store/repositories/scheduler-repository.d.ts +50 -0
- package/dist/store/repositories/scheduler-repository.js +123 -0
- package/dist/store/repositories/session-repository.d.ts +33 -0
- package/dist/store/repositories/session-repository.js +82 -0
- package/dist/store/repositories/todo-repository.d.ts +31 -0
- package/dist/store/repositories/todo-repository.js +77 -0
- package/dist/store/repositories/tracker-repository.d.ts +25 -0
- package/dist/store/repositories/tracker-repository.js +43 -0
- package/dist/store/repositories/vericify-repository.d.ts +32 -0
- package/dist/store/repositories/vericify-repository.js +58 -0
- package/dist/store/skills-install.d.ts +28 -0
- package/dist/store/skills-install.js +86 -0
- package/dist/store/state-reader.d.ts +49 -0
- package/dist/store/state-reader.js +111 -0
- package/dist/store/store-artifacts.d.ts +12 -0
- package/dist/store/store-artifacts.js +138 -0
- package/dist/store/store-snapshot.d.ts +19 -0
- package/dist/store/store-snapshot.js +140 -0
- package/dist/store/topology-bake.d.ts +15 -0
- package/dist/store/topology-bake.js +215 -0
- package/dist/store/types.d.ts +155 -0
- package/dist/store/types.js +35 -0
- package/dist/store/workspace-snapshot.d.ts +26 -0
- package/dist/store/workspace-snapshot.js +107 -0
- package/dist/store/write-queue.d.ts +7 -0
- package/dist/store/write-queue.js +26 -0
- package/dist/todo-state.d.ts +41 -0
- package/dist/todo-state.js +399 -0
- package/dist/tools-agent.d.ts +7 -0
- package/dist/tools-agent.js +1542 -0
- package/dist/tools-discovery.d.ts +6 -0
- package/dist/tools-discovery.js +178 -0
- package/dist/tools-drift.d.ts +13 -0
- package/dist/tools-drift.js +357 -0
- package/dist/tools-files.d.ts +6 -0
- package/dist/tools-files.js +679 -0
- package/dist/tools-framework.d.ts +7 -0
- package/dist/tools-framework.js +1414 -0
- package/dist/tools-git.d.ts +6 -0
- package/dist/tools-git.js +183 -0
- package/dist/tools-handoff.d.ts +32 -0
- package/dist/tools-handoff.js +489 -0
- package/dist/tools-lifecycle.d.ts +6 -0
- package/dist/tools-lifecycle.js +205 -0
- package/dist/tools-memory.d.ts +6 -0
- package/dist/tools-memory.js +260 -0
- package/dist/tools-scheduler.d.ts +6 -0
- package/dist/tools-scheduler.js +228 -0
- package/dist/tools-skills.d.ts +3 -0
- package/dist/tools-skills.js +104 -0
- package/dist/tools-todo.d.ts +6 -0
- package/dist/tools-todo.js +154 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.js +33 -0
- package/dist/tracker-adapters.d.ts +74 -0
- package/dist/tracker-adapters.js +776 -0
- package/dist/tracker-sync.d.ts +10 -0
- package/dist/tracker-sync.js +84 -0
- package/dist/tui/agent-runner.d.ts +137 -0
- package/dist/tui/agent-runner.js +466 -0
- package/dist/tui/agent-worker.d.ts +10 -0
- package/dist/tui/agent-worker.js +347 -0
- package/dist/tui/chat.d.ts +84 -0
- package/dist/tui/chat.js +368 -0
- package/dist/tui/commands.d.ts +57 -0
- package/dist/tui/commands.js +432 -0
- package/dist/tui/dashboard.d.ts +24 -0
- package/dist/tui/dashboard.js +110 -0
- package/dist/tui/index.d.ts +114 -0
- package/dist/tui/index.js +1059 -0
- package/dist/tui/input.d.ts +49 -0
- package/dist/tui/input.js +336 -0
- package/dist/tui/layout.d.ts +116 -0
- package/dist/tui/layout.js +367 -0
- package/dist/tui/ollama.d.ts +116 -0
- package/dist/tui/ollama.js +192 -0
- package/dist/tui/openai-compatible.d.ts +63 -0
- package/dist/tui/openai-compatible.js +370 -0
- package/dist/tui/provider-discovery.d.ts +59 -0
- package/dist/tui/provider-discovery.js +530 -0
- package/dist/tui/renderer.d.ts +166 -0
- package/dist/tui/renderer.js +304 -0
- package/dist/tui/tabs.d.ts +70 -0
- package/dist/tui/tabs.js +208 -0
- package/dist/tui/telemetry.d.ts +56 -0
- package/dist/tui/telemetry.js +106 -0
- package/dist/vericify-bridge.d.ts +146 -0
- package/dist/vericify-bridge.js +571 -0
- package/dist/vericify-context.d.ts +10 -0
- package/dist/vericify-context.js +72 -0
- package/dist/workspace-manager.d.ts +107 -0
- package/dist/workspace-manager.js +636 -0
- package/package.json +83 -0
package/dist/kanban.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type KanbanColumn = "backlog" | "blocked" | "in_progress" | "gated" | "done";
|
|
2
|
+
export interface AceKanbanCard {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
source: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AceKanbanBoard {
|
|
8
|
+
backlog: AceKanbanCard[];
|
|
9
|
+
blocked: AceKanbanCard[];
|
|
10
|
+
in_progress: AceKanbanCard[];
|
|
11
|
+
gated: AceKanbanCard[];
|
|
12
|
+
done: AceKanbanCard[];
|
|
13
|
+
}
|
|
14
|
+
export interface AceKanbanSnapshot {
|
|
15
|
+
version: number;
|
|
16
|
+
generated_at: string;
|
|
17
|
+
trigger: string;
|
|
18
|
+
board: AceKanbanBoard;
|
|
19
|
+
counts: Record<KanbanColumn, number>;
|
|
20
|
+
html_path: string;
|
|
21
|
+
json_path: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function renderKanbanHtml(snapshot: AceKanbanSnapshot): string;
|
|
24
|
+
export declare function refreshKanbanArtifacts(trigger: string): AceKanbanSnapshot;
|
|
25
|
+
export declare function getOrRefreshKanbanSnapshot(trigger: string): AceKanbanSnapshot;
|
|
26
|
+
export declare function shouldAutoRefreshKanbanForPath(path: string): boolean;
|
|
27
|
+
//# sourceMappingURL=kanban.d.ts.map
|
package/dist/kanban.js
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, safeRead, safeWrite, wsPath } from "./helpers.js";
|
|
2
|
+
import { isReadError, slugify } from "./shared.js";
|
|
3
|
+
import { readHandoffRegistry } from "./handoff-registry.js";
|
|
4
|
+
import { readTodoState } from "./todo-state.js";
|
|
5
|
+
/** Debounce threshold in milliseconds. Skip re-render if within this window. */
|
|
6
|
+
const KANBAN_DEBOUNCE_MS = 2000;
|
|
7
|
+
let lastKanbanRenderTimestamp = 0;
|
|
8
|
+
const KANBAN_JSON_REL = "agent-state/kanban.json";
|
|
9
|
+
const KANBAN_HTML_REL = "agent-state/kanban.html";
|
|
10
|
+
const COLUMNS = ["backlog", "blocked", "in_progress", "gated", "done"];
|
|
11
|
+
function nowIso() {
|
|
12
|
+
return new Date().toISOString();
|
|
13
|
+
}
|
|
14
|
+
function emptyBoard() {
|
|
15
|
+
return {
|
|
16
|
+
backlog: [],
|
|
17
|
+
blocked: [],
|
|
18
|
+
in_progress: [],
|
|
19
|
+
gated: [],
|
|
20
|
+
done: [],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function escapeHtml(input) {
|
|
24
|
+
return input
|
|
25
|
+
.replace(/&/g, "&")
|
|
26
|
+
.replace(/</g, "<")
|
|
27
|
+
.replace(/>/g, ">")
|
|
28
|
+
.replace(/"/g, """)
|
|
29
|
+
.replace(/'/g, "'");
|
|
30
|
+
}
|
|
31
|
+
function tryParseJson(raw) {
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function parseChecklistItems(todoRaw) {
|
|
44
|
+
const items = [];
|
|
45
|
+
let section = "General";
|
|
46
|
+
for (const line of todoRaw.split(/\r?\n/)) {
|
|
47
|
+
const header = line.match(/^##\s+(.+)$/);
|
|
48
|
+
if (header) {
|
|
49
|
+
section = header[1]?.trim() || "General";
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const item = line.match(/^- \[( |x|X)\]\s+(.+)$/);
|
|
53
|
+
if (!item) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
items.push({
|
|
57
|
+
checked: item[1]?.toLowerCase() === "x",
|
|
58
|
+
section,
|
|
59
|
+
title: item[2]?.trim() || "Untitled task",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return items;
|
|
63
|
+
}
|
|
64
|
+
function classifyTodoItem(item) {
|
|
65
|
+
if (item.checked) {
|
|
66
|
+
return "done";
|
|
67
|
+
}
|
|
68
|
+
const section = item.section.toLowerCase();
|
|
69
|
+
const title = item.title.toLowerCase();
|
|
70
|
+
if (/\bblocked?\b|\bblocker\b|\bstuck\b|\bwaiting\b/.test(title)) {
|
|
71
|
+
return "blocked";
|
|
72
|
+
}
|
|
73
|
+
if (/\bin progress\b|\bwip\b|\bdoing\b|\bactive\b/.test(title)) {
|
|
74
|
+
return "in_progress";
|
|
75
|
+
}
|
|
76
|
+
if (section.includes("verification")) {
|
|
77
|
+
return "gated";
|
|
78
|
+
}
|
|
79
|
+
if (section.includes("active")) {
|
|
80
|
+
return "in_progress";
|
|
81
|
+
}
|
|
82
|
+
return "backlog";
|
|
83
|
+
}
|
|
84
|
+
function addTodoCards(board) {
|
|
85
|
+
const todoState = readTodoState();
|
|
86
|
+
if (todoState.order.length > 0) {
|
|
87
|
+
for (const nodeId of todoState.order) {
|
|
88
|
+
const node = todoState.nodes[nodeId];
|
|
89
|
+
if (!node)
|
|
90
|
+
continue;
|
|
91
|
+
board[node.status].push({
|
|
92
|
+
id: node.id,
|
|
93
|
+
title: `${node.title} (${node.section})`,
|
|
94
|
+
source: "agent-state/todo-state.json",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const todoRaw = safeRead(`${ACE_TASKS_ROOT_REL}/todo.md`);
|
|
100
|
+
if (isReadError(todoRaw)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const checklist = parseChecklistItems(todoRaw);
|
|
104
|
+
checklist.forEach((item, idx) => {
|
|
105
|
+
const lane = classifyTodoItem(item);
|
|
106
|
+
board[lane].push({
|
|
107
|
+
id: `todo-${idx + 1}-${slugify(item.title)}`,
|
|
108
|
+
title: `${item.title} (${item.section})`,
|
|
109
|
+
source: `${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function extractInlineValue(raw, key) {
|
|
114
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
115
|
+
const re = new RegExp(`^-\\s*${escaped}:\\s*(.+)$`, "im");
|
|
116
|
+
const match = raw.match(re);
|
|
117
|
+
if (!match || !match[1]) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
return match[1].replace(/`/g, "").trim();
|
|
121
|
+
}
|
|
122
|
+
function addStatusCard(board) {
|
|
123
|
+
const statusRaw = safeRead("agent-state/STATUS.md");
|
|
124
|
+
if (isReadError(statusRaw)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const currentRole = extractInlineValue(statusRaw, "Current role");
|
|
128
|
+
if (!currentRole) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const phase = extractInlineValue(statusRaw, "Current phase") || "unknown phase";
|
|
132
|
+
const blockers = extractInlineValue(statusRaw, "Blockers") || "unknown";
|
|
133
|
+
const objective = extractInlineValue(statusRaw, "Current objective");
|
|
134
|
+
const title = objective
|
|
135
|
+
? `${currentRole} (${phase}) - ${objective}`
|
|
136
|
+
: `${currentRole} (${phase})`;
|
|
137
|
+
const lane = blockers.toLowerCase() === "none" ? "in_progress" : "blocked";
|
|
138
|
+
board[lane].push({
|
|
139
|
+
id: "status-current-role",
|
|
140
|
+
title,
|
|
141
|
+
source: "agent-state/STATUS.md",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function addHandoffCard(board) {
|
|
145
|
+
const handoffRaw = safeRead("agent-state/HANDOFF.json");
|
|
146
|
+
if (isReadError(handoffRaw)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const parsed = tryParseJson(handoffRaw);
|
|
150
|
+
if (!parsed) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const transition = (parsed.transition && typeof parsed.transition === "object" ? parsed.transition : undefined);
|
|
154
|
+
if (!transition) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const from = String(transition.from ?? "unknown-from");
|
|
158
|
+
const to = String(transition.to ?? "unknown-to");
|
|
159
|
+
const status = String(transition.status ?? "READY").toUpperCase();
|
|
160
|
+
const reason = String(transition.reason ?? "handoff reason unspecified");
|
|
161
|
+
let lane = "gated";
|
|
162
|
+
if (status === "BLOCKED") {
|
|
163
|
+
lane = "blocked";
|
|
164
|
+
}
|
|
165
|
+
else if (status === "DONE") {
|
|
166
|
+
lane = "done";
|
|
167
|
+
}
|
|
168
|
+
else if (status === "READY_FOR_REVIEW" || status === "READY") {
|
|
169
|
+
lane = "gated";
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
lane = "in_progress";
|
|
173
|
+
}
|
|
174
|
+
board[lane].push({
|
|
175
|
+
id: `handoff-${slugify(from)}-to-${slugify(to)}`,
|
|
176
|
+
title: `${from} -> ${to} (${status}): ${reason}`,
|
|
177
|
+
source: "agent-state/HANDOFF.json",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function addHandoffRegistryCards(board) {
|
|
181
|
+
const registry = readHandoffRegistry();
|
|
182
|
+
const records = Object.values(registry.handoffs).sort((a, b) => b.updated_at.localeCompare(a.updated_at));
|
|
183
|
+
for (const record of records.slice(0, 24)) {
|
|
184
|
+
const lane = record.status === "blocked"
|
|
185
|
+
? "blocked"
|
|
186
|
+
: record.status === "completed"
|
|
187
|
+
? "done"
|
|
188
|
+
: record.status === "accepted"
|
|
189
|
+
? "in_progress"
|
|
190
|
+
: "backlog";
|
|
191
|
+
board[lane].push({
|
|
192
|
+
id: `registry-${slugify(record.handoff_id)}`,
|
|
193
|
+
title: `${record.from} -> ${record.to} (${record.status.toUpperCase()}): ${record.title}`,
|
|
194
|
+
source: "agent-state/handoff-registry.json",
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function normalizeBoardOrder(board) {
|
|
199
|
+
for (const name of COLUMNS) {
|
|
200
|
+
board[name].sort((a, b) => a.title.localeCompare(b.title));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function renderCard(card) {
|
|
204
|
+
return [
|
|
205
|
+
`<article class="card">`,
|
|
206
|
+
`<h3>${escapeHtml(card.title)}</h3>`,
|
|
207
|
+
`<p class="meta">${escapeHtml(card.id)} | ${escapeHtml(card.source)}</p>`,
|
|
208
|
+
`</article>`,
|
|
209
|
+
].join("");
|
|
210
|
+
}
|
|
211
|
+
export function renderKanbanHtml(snapshot) {
|
|
212
|
+
const sections = COLUMNS.map((name) => {
|
|
213
|
+
const cards = snapshot.board[name];
|
|
214
|
+
return [
|
|
215
|
+
`<section class="column">`,
|
|
216
|
+
`<header><h2>${escapeHtml(name.replace(/_/g, " "))}</h2><span>${cards.length}</span></header>`,
|
|
217
|
+
`<div class="cards">${cards.map(renderCard).join("") || '<p class="empty">No cards</p>'}</div>`,
|
|
218
|
+
`</section>`,
|
|
219
|
+
].join("");
|
|
220
|
+
}).join("");
|
|
221
|
+
return [
|
|
222
|
+
"<!doctype html>",
|
|
223
|
+
"<html lang=\"en\">",
|
|
224
|
+
"<head>",
|
|
225
|
+
"<meta charset=\"utf-8\" />",
|
|
226
|
+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />",
|
|
227
|
+
"<title>ACE Swarm Kanban</title>",
|
|
228
|
+
"<style>",
|
|
229
|
+
":root{--bg:#f6f4ef;--ink:#1f1f1d;--line:#d8d2c5;--card:#fffcf4;--accent:#d56822}",
|
|
230
|
+
"*{box-sizing:border-box}",
|
|
231
|
+
"body{margin:0;font-family:'IBM Plex Sans','Segoe UI',sans-serif;background:radial-gradient(circle at 20% 20%,#fffaf0 0%,#f3efe4 45%,#ece6d8 100%);color:var(--ink)}",
|
|
232
|
+
"main{max-width:1600px;margin:0 auto;padding:20px}",
|
|
233
|
+
"header.top{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:16px}",
|
|
234
|
+
".title{display:flex;align-items:center;gap:10px}",
|
|
235
|
+
".spinner{width:14px;height:14px;border:2px solid var(--accent);border-top-color:transparent;border-radius:999px;animation:spin 1s linear infinite}",
|
|
236
|
+
"@keyframes spin{to{transform:rotate(360deg)}}",
|
|
237
|
+
"h1{margin:0;font-family:'Space Grotesk','Avenir Next',sans-serif;font-size:24px}",
|
|
238
|
+
".stamp{margin:0;font-size:12px;opacity:.75}",
|
|
239
|
+
".grid{display:grid;grid-template-columns:repeat(5,minmax(220px,1fr));gap:12px}",
|
|
240
|
+
".column{background:rgba(255,255,255,.62);border:1px solid var(--line);border-radius:12px;min-height:220px}",
|
|
241
|
+
".column>header{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;border-bottom:1px solid var(--line)}",
|
|
242
|
+
".column h2{margin:0;font-size:14px;text-transform:capitalize}",
|
|
243
|
+
".column span{background:var(--accent);color:#fff;border-radius:999px;padding:2px 8px;font-size:12px}",
|
|
244
|
+
".cards{display:flex;flex-direction:column;gap:8px;padding:10px}",
|
|
245
|
+
".card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px}",
|
|
246
|
+
".card h3{margin:0 0 6px;font-size:13px;line-height:1.35}",
|
|
247
|
+
".meta{margin:0;font-size:11px;opacity:.75;word-break:break-all}",
|
|
248
|
+
".empty{margin:0;padding:8px;font-size:12px;opacity:.55}",
|
|
249
|
+
"@media (max-width:1200px){.grid{grid-template-columns:repeat(2,minmax(220px,1fr));}}",
|
|
250
|
+
"@media (max-width:640px){.grid{grid-template-columns:1fr;}}",
|
|
251
|
+
"</style>",
|
|
252
|
+
"</head>",
|
|
253
|
+
"<body>",
|
|
254
|
+
"<main>",
|
|
255
|
+
"<header class=\"top\">",
|
|
256
|
+
"<div>",
|
|
257
|
+
"<div class=\"title\"><span class=\"spinner\" aria-hidden=\"true\"></span><h1>ACE Swarm Kanban</h1></div>",
|
|
258
|
+
`<p class="stamp">trigger: ${escapeHtml(snapshot.trigger)}</p>`,
|
|
259
|
+
"</div>",
|
|
260
|
+
`<p class="stamp">updated: ${escapeHtml(snapshot.generated_at)}</p>`,
|
|
261
|
+
"</header>",
|
|
262
|
+
`<section class="grid">${sections}</section>`,
|
|
263
|
+
"</main>",
|
|
264
|
+
"</body>",
|
|
265
|
+
"</html>",
|
|
266
|
+
].join("");
|
|
267
|
+
}
|
|
268
|
+
export function refreshKanbanArtifacts(trigger) {
|
|
269
|
+
// Debounce: skip expensive re-render if within threshold
|
|
270
|
+
const now = Date.now();
|
|
271
|
+
if (now - lastKanbanRenderTimestamp < KANBAN_DEBOUNCE_MS) {
|
|
272
|
+
// Return cached snapshot if available
|
|
273
|
+
const cached = getOrRefreshKanbanSnapshot(trigger);
|
|
274
|
+
if (cached.generated_at)
|
|
275
|
+
return cached;
|
|
276
|
+
}
|
|
277
|
+
lastKanbanRenderTimestamp = now;
|
|
278
|
+
const board = emptyBoard();
|
|
279
|
+
addTodoCards(board);
|
|
280
|
+
addStatusCard(board);
|
|
281
|
+
addHandoffCard(board);
|
|
282
|
+
addHandoffRegistryCards(board);
|
|
283
|
+
normalizeBoardOrder(board);
|
|
284
|
+
const snapshot = {
|
|
285
|
+
version: 1,
|
|
286
|
+
generated_at: nowIso(),
|
|
287
|
+
trigger,
|
|
288
|
+
board,
|
|
289
|
+
counts: {
|
|
290
|
+
backlog: board.backlog.length,
|
|
291
|
+
blocked: board.blocked.length,
|
|
292
|
+
in_progress: board.in_progress.length,
|
|
293
|
+
gated: board.gated.length,
|
|
294
|
+
done: board.done.length,
|
|
295
|
+
},
|
|
296
|
+
html_path: wsPath(KANBAN_HTML_REL),
|
|
297
|
+
json_path: wsPath(KANBAN_JSON_REL),
|
|
298
|
+
};
|
|
299
|
+
safeWrite(KANBAN_HTML_REL, renderKanbanHtml(snapshot));
|
|
300
|
+
safeWrite(KANBAN_JSON_REL, JSON.stringify(snapshot, null, 2));
|
|
301
|
+
return snapshot;
|
|
302
|
+
}
|
|
303
|
+
export function getOrRefreshKanbanSnapshot(trigger) {
|
|
304
|
+
const raw = safeRead(KANBAN_JSON_REL);
|
|
305
|
+
if (!isReadError(raw)) {
|
|
306
|
+
const parsed = tryParseJson(raw);
|
|
307
|
+
const version = typeof parsed?.version === "number" ? parsed.version : undefined;
|
|
308
|
+
const generated = typeof parsed?.generated_at === "string" ? parsed.generated_at : undefined;
|
|
309
|
+
const board = parsed?.board;
|
|
310
|
+
const counts = parsed?.counts;
|
|
311
|
+
const htmlPath = typeof parsed?.html_path === "string" ? parsed.html_path : undefined;
|
|
312
|
+
const jsonPath = typeof parsed?.json_path === "string" ? parsed.json_path : undefined;
|
|
313
|
+
const savedTrigger = typeof parsed?.trigger === "string" ? parsed.trigger : "cached";
|
|
314
|
+
if (version === 1 && generated && board && counts && htmlPath && jsonPath) {
|
|
315
|
+
return {
|
|
316
|
+
version,
|
|
317
|
+
generated_at: generated,
|
|
318
|
+
trigger: savedTrigger,
|
|
319
|
+
board,
|
|
320
|
+
counts,
|
|
321
|
+
html_path: htmlPath,
|
|
322
|
+
json_path: jsonPath,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return refreshKanbanArtifacts(trigger);
|
|
327
|
+
}
|
|
328
|
+
export function shouldAutoRefreshKanbanForPath(path) {
|
|
329
|
+
const normalized = path.replace(/\\/g, "/").replace(/^\.?\//, "");
|
|
330
|
+
if (normalized === KANBAN_JSON_REL || normalized === KANBAN_HTML_REL) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
return (normalized.startsWith(`${ACE_TASKS_ROOT_REL}/`) ||
|
|
334
|
+
normalized.startsWith(`${ACE_ROOT_REL}/agent-state/`) ||
|
|
335
|
+
normalized.startsWith(`${ACE_ROOT_REL}/global-state/`) ||
|
|
336
|
+
normalized.startsWith("ace-mcp-server/src/") ||
|
|
337
|
+
/(^|\/)SWARM_HANDOFF\.[^/]+\.json$/.test(normalized));
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=kanban.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type BridgeResult, type ModelBridgeClients } from "./model-bridge.js";
|
|
2
|
+
import type { AceContextTier } from "./ace-context.js";
|
|
3
|
+
export interface LocalModelRuntimeConfig {
|
|
4
|
+
workspaceRoot: string;
|
|
5
|
+
provider: string;
|
|
6
|
+
model: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
ollamaUrl?: string;
|
|
9
|
+
providerBaseUrls: Record<string, string>;
|
|
10
|
+
notes: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface RunLocalModelTaskOptions {
|
|
13
|
+
task: string;
|
|
14
|
+
role?: string;
|
|
15
|
+
workspaceRoot?: string;
|
|
16
|
+
provider?: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
ollamaUrl?: string;
|
|
20
|
+
maxTurns?: number;
|
|
21
|
+
tier?: AceContextTier | "auto";
|
|
22
|
+
toolScope?: string[];
|
|
23
|
+
clients?: ModelBridgeClients;
|
|
24
|
+
}
|
|
25
|
+
export interface RunLocalModelTaskResult {
|
|
26
|
+
runtime: LocalModelRuntimeConfig;
|
|
27
|
+
role: string;
|
|
28
|
+
routingSummary?: string;
|
|
29
|
+
result: BridgeResult;
|
|
30
|
+
}
|
|
31
|
+
export declare function createDefaultModelBridgeClients(runtime: Pick<LocalModelRuntimeConfig, "providerBaseUrls">): ModelBridgeClients;
|
|
32
|
+
export declare function resolveLocalModelRuntime(input: {
|
|
33
|
+
workspaceRoot?: string;
|
|
34
|
+
provider?: string;
|
|
35
|
+
model?: string;
|
|
36
|
+
baseUrl?: string;
|
|
37
|
+
ollamaUrl?: string;
|
|
38
|
+
}): LocalModelRuntimeConfig;
|
|
39
|
+
export declare function runLocalModelTask(options: RunLocalModelTaskOptions): Promise<RunLocalModelTaskResult>;
|
|
40
|
+
//# sourceMappingURL=local-model-runtime.d.ts.map
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { ROLE_ENUM, scoreDomains } from "./shared.js";
|
|
4
|
+
import { resolveWorkspaceRoot } from "./helpers.js";
|
|
5
|
+
import { executeAceInternalTool } from "./ace-internal-tools.js";
|
|
6
|
+
import { ModelBridge } from "./model-bridge.js";
|
|
7
|
+
import { OllamaClient } from "./tui/ollama.js";
|
|
8
|
+
import { OpenAICompatibleClient, diagnoseChatRuntimeConfig, } from "./tui/openai-compatible.js";
|
|
9
|
+
import { discoverProviderContext } from "./tui/provider-discovery.js";
|
|
10
|
+
function extractTextContent(result) {
|
|
11
|
+
if (!result || typeof result !== "object")
|
|
12
|
+
return "";
|
|
13
|
+
const content = Array.isArray(result.content) ? result.content : [];
|
|
14
|
+
return content
|
|
15
|
+
.filter((entry) => Boolean(entry) &&
|
|
16
|
+
typeof entry === "object" &&
|
|
17
|
+
entry.type === "text")
|
|
18
|
+
.map((entry) => String(entry.text ?? "").trim())
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join("\n");
|
|
21
|
+
}
|
|
22
|
+
function normalizeRoleCandidate(input) {
|
|
23
|
+
if (!input)
|
|
24
|
+
return undefined;
|
|
25
|
+
const normalized = input.trim().toLowerCase().replace(/^ace-/, "").replace(/[^a-z0-9]+/g, "");
|
|
26
|
+
const candidate = normalized === "coder" ? "coders" : normalized;
|
|
27
|
+
return ROLE_ENUM.options.includes(candidate)
|
|
28
|
+
? candidate
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
function parseRoleFromRoutingSummary(summary) {
|
|
32
|
+
const match = summary.match(/\*\*Primary Swarm Agent\(s\):\*\*\s*([^\n]+)/i);
|
|
33
|
+
if (!match?.[1])
|
|
34
|
+
return undefined;
|
|
35
|
+
const firstAgent = match[1]
|
|
36
|
+
.split(",")
|
|
37
|
+
.map((entry) => entry.trim())
|
|
38
|
+
.find(Boolean);
|
|
39
|
+
return normalizeRoleCandidate(firstAgent);
|
|
40
|
+
}
|
|
41
|
+
function hasAlignedTaskContract(workspaceRoot) {
|
|
42
|
+
const required = [
|
|
43
|
+
"agent-state/TASK.md",
|
|
44
|
+
"agent-state/SCOPE.md",
|
|
45
|
+
"agent-state/QUALITY_GATES.md",
|
|
46
|
+
"agent-state/HANDOFF.json",
|
|
47
|
+
];
|
|
48
|
+
return required.every((relativePath) => {
|
|
49
|
+
const absolute = resolve(workspaceRoot, relativePath);
|
|
50
|
+
if (!existsSync(absolute))
|
|
51
|
+
return false;
|
|
52
|
+
return readFileSync(absolute, "utf-8").trim().length > 0;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function fallbackRoleForTask(task, workspaceRoot) {
|
|
56
|
+
if (!hasAlignedTaskContract(workspaceRoot)) {
|
|
57
|
+
return "orchestrator";
|
|
58
|
+
}
|
|
59
|
+
const { domain } = scoreDomains(task);
|
|
60
|
+
switch (domain) {
|
|
61
|
+
case "engineering":
|
|
62
|
+
return "coders";
|
|
63
|
+
case "venture":
|
|
64
|
+
return "vos";
|
|
65
|
+
case "ux":
|
|
66
|
+
return "ui";
|
|
67
|
+
default:
|
|
68
|
+
return "orchestrator";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function resolveRole(task, workspaceRoot, sessionId, requestedRole) {
|
|
72
|
+
const explicitRole = normalizeRoleCandidate(requestedRole);
|
|
73
|
+
if (explicitRole) {
|
|
74
|
+
return { role: explicitRole, routingSummary: undefined };
|
|
75
|
+
}
|
|
76
|
+
const routing = await executeAceInternalTool("route_task", { description: task, domain: "unknown" }, sessionId);
|
|
77
|
+
const routingSummary = extractTextContent(routing);
|
|
78
|
+
const routedRole = parseRoleFromRoutingSummary(routingSummary);
|
|
79
|
+
const fallbackRole = fallbackRoleForTask(task, workspaceRoot);
|
|
80
|
+
return {
|
|
81
|
+
role: routedRole && !(routedRole === "orchestrator" && fallbackRole !== "orchestrator")
|
|
82
|
+
? routedRole
|
|
83
|
+
: fallbackRole,
|
|
84
|
+
routingSummary,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function resolveTier(requested, provider, model, role) {
|
|
88
|
+
if (requested && requested !== "auto")
|
|
89
|
+
return requested;
|
|
90
|
+
const normalizedProvider = provider.trim().toLowerCase();
|
|
91
|
+
const normalizedModel = model.trim().toLowerCase();
|
|
92
|
+
if (role === "orchestrator")
|
|
93
|
+
return "compressed";
|
|
94
|
+
if (normalizedProvider !== "ollama")
|
|
95
|
+
return "full";
|
|
96
|
+
if (/(70b|72b|90b|405b|claude|gpt-|codex|gemini|o[1345])/.test(normalizedModel)) {
|
|
97
|
+
return "full";
|
|
98
|
+
}
|
|
99
|
+
if (/(7b|8b|mini|small|phi|tiny)/.test(normalizedModel)) {
|
|
100
|
+
return "brief";
|
|
101
|
+
}
|
|
102
|
+
return "compressed";
|
|
103
|
+
}
|
|
104
|
+
export function createDefaultModelBridgeClients(runtime) {
|
|
105
|
+
const providerConfigs = {};
|
|
106
|
+
for (const [provider, baseUrl] of Object.entries(runtime.providerBaseUrls)) {
|
|
107
|
+
providerConfigs[provider] = { baseUrl };
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
ollama: new OllamaClient(runtime.providerBaseUrls.ollama),
|
|
111
|
+
openai: new OpenAICompatibleClient({ providerConfigs }),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export function resolveLocalModelRuntime(input) {
|
|
115
|
+
const workspaceRoot = input.workspaceRoot
|
|
116
|
+
? resolve(input.workspaceRoot)
|
|
117
|
+
: resolveWorkspaceRoot();
|
|
118
|
+
const discovered = discoverProviderContext({
|
|
119
|
+
workspaceRoot,
|
|
120
|
+
cliProvider: input.provider,
|
|
121
|
+
cliModel: input.model,
|
|
122
|
+
cliBaseUrl: input.baseUrl,
|
|
123
|
+
cliOllamaUrl: input.ollamaUrl,
|
|
124
|
+
});
|
|
125
|
+
if (discovered.provider === "ollama" && !discovered.ollamaUrl) {
|
|
126
|
+
throw new Error("Ollama base URL is not configured. Provide `--base-url`/`ollama_url`, set OLLAMA_HOST, or run `ace doctor --llm ollama --scan`.");
|
|
127
|
+
}
|
|
128
|
+
if (discovered.provider !== "ollama") {
|
|
129
|
+
const diagnosis = diagnoseChatRuntimeConfig(discovered.provider, discovered.model, {
|
|
130
|
+
baseUrl: discovered.baseUrl,
|
|
131
|
+
});
|
|
132
|
+
if (!diagnosis.ok) {
|
|
133
|
+
throw new Error(diagnosis.message);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
workspaceRoot,
|
|
138
|
+
provider: discovered.provider,
|
|
139
|
+
model: discovered.model,
|
|
140
|
+
baseUrl: discovered.baseUrl,
|
|
141
|
+
ollamaUrl: discovered.ollamaUrl,
|
|
142
|
+
providerBaseUrls: discovered.providerBaseUrls,
|
|
143
|
+
notes: discovered.notes,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export async function runLocalModelTask(options) {
|
|
147
|
+
const runtime = resolveLocalModelRuntime({
|
|
148
|
+
workspaceRoot: options.workspaceRoot,
|
|
149
|
+
provider: options.provider,
|
|
150
|
+
model: options.model,
|
|
151
|
+
baseUrl: options.baseUrl,
|
|
152
|
+
ollamaUrl: options.ollamaUrl,
|
|
153
|
+
});
|
|
154
|
+
const bridge = new ModelBridge(options.clients ?? createDefaultModelBridgeClients(runtime));
|
|
155
|
+
const { role, routingSummary } = await resolveRole(options.task, runtime.workspaceRoot, undefined, options.role);
|
|
156
|
+
const tier = resolveTier(options.tier, runtime.provider, runtime.model, role);
|
|
157
|
+
const result = await bridge.run({
|
|
158
|
+
task: options.task,
|
|
159
|
+
role,
|
|
160
|
+
workspace: runtime.workspaceRoot,
|
|
161
|
+
tier,
|
|
162
|
+
maxTurns: options.maxTurns ?? (role === "orchestrator" ? 6 : 4),
|
|
163
|
+
provider: runtime.provider,
|
|
164
|
+
model: runtime.model,
|
|
165
|
+
toolScope: options.toolScope,
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
runtime,
|
|
169
|
+
role,
|
|
170
|
+
routingSummary,
|
|
171
|
+
result,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=local-model-runtime.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type AceContextTier } from "./ace-context.js";
|
|
2
|
+
import type { OllamaClient } from "./tui/ollama.js";
|
|
3
|
+
import type { OpenAICompatibleClient } from "./tui/openai-compatible.js";
|
|
4
|
+
export interface BridgeToolCall {
|
|
5
|
+
tool: string;
|
|
6
|
+
input?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface BridgeToolResult {
|
|
9
|
+
tool: string;
|
|
10
|
+
ok: boolean;
|
|
11
|
+
summary: string;
|
|
12
|
+
isError: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface BridgeResult {
|
|
15
|
+
bridge_id: string;
|
|
16
|
+
role: string;
|
|
17
|
+
status: "completed" | "needs_input" | "failed" | "max_turns";
|
|
18
|
+
summary: string;
|
|
19
|
+
turns: number;
|
|
20
|
+
tool_calls: BridgeToolResult[];
|
|
21
|
+
child_results: BridgeResult[];
|
|
22
|
+
}
|
|
23
|
+
export interface ModelBridgeClients {
|
|
24
|
+
ollama: Pick<OllamaClient, "chat" | "abort">;
|
|
25
|
+
openai: Pick<OpenAICompatibleClient, "chat" | "abort">;
|
|
26
|
+
}
|
|
27
|
+
export interface ModelBridgeRunOptions {
|
|
28
|
+
task: string;
|
|
29
|
+
role: string;
|
|
30
|
+
workspace: string;
|
|
31
|
+
tier?: AceContextTier;
|
|
32
|
+
numCtx?: number;
|
|
33
|
+
maxTurns: number;
|
|
34
|
+
provider: string;
|
|
35
|
+
model: string;
|
|
36
|
+
toolScope?: string[];
|
|
37
|
+
parentBridge?: string;
|
|
38
|
+
onToolCall?: (tool: string, args: Record<string, unknown>) => void;
|
|
39
|
+
onToolResult?: (tool: string, result: BridgeToolResult) => void;
|
|
40
|
+
onOutput?: (text: string) => void;
|
|
41
|
+
onThinking?: (text: string) => void;
|
|
42
|
+
}
|
|
43
|
+
export declare class ModelBridge {
|
|
44
|
+
private clients;
|
|
45
|
+
private activeProviderClient;
|
|
46
|
+
private bridgeId;
|
|
47
|
+
private currentRunChildResults;
|
|
48
|
+
constructor(clients: ModelBridgeClients);
|
|
49
|
+
interrupt(): void;
|
|
50
|
+
spawn(options: ModelBridgeRunOptions): Promise<BridgeResult>;
|
|
51
|
+
private selectToolScope;
|
|
52
|
+
run(options: ModelBridgeRunOptions): Promise<BridgeResult>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=model-bridge.d.ts.map
|