stageflow 0.36.0 → 0.40.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/README.md +61 -26
- package/dist/agent/claudeAdapter.js +21 -1
- package/dist/agent/claudeTools.d.ts +13 -0
- package/dist/agent/claudeTools.js +98 -0
- package/dist/agent/piAdapter.d.ts +9 -1
- package/dist/agent/piAdapter.js +59 -18
- package/dist/agent/piIsolatedMcp.js +14 -2
- package/dist/agent/piIsolatedMcpProbe.d.ts +5 -1
- package/dist/agent/piIsolatedMcpProbe.js +16 -30
- package/dist/agent/port.d.ts +5 -0
- package/dist/agent/sandboxPiTools.d.ts +99 -0
- package/dist/agent/sandboxPiTools.js +109 -0
- package/dist/agents/agentId.d.ts +8 -0
- package/dist/agents/agentId.js +27 -0
- package/dist/agents/approvalBroker.d.ts +16 -0
- package/dist/agents/approvalBroker.js +45 -0
- package/dist/agents/authorChat.d.ts +19 -0
- package/dist/agents/authorChat.js +63 -0
- package/dist/agents/chatTurn.d.ts +23 -0
- package/dist/agents/chatTurn.js +77 -0
- package/dist/agents/communications/agentmail.d.ts +19 -0
- package/dist/agents/communications/agentmail.js +46 -0
- package/dist/agents/communications/agentmailListener.d.ts +59 -0
- package/dist/agents/communications/agentmailListener.js +183 -0
- package/dist/agents/communications/allowlist.d.ts +10 -0
- package/dist/agents/communications/allowlist.js +36 -0
- package/dist/agents/communications/channelConnections.d.ts +3 -0
- package/dist/agents/communications/channelConnections.js +51 -0
- package/dist/agents/communications/delivery.d.ts +53 -0
- package/dist/agents/communications/delivery.js +142 -0
- package/dist/agents/communications/email.d.ts +26 -0
- package/dist/agents/communications/email.js +20 -0
- package/dist/agents/communications/identity.d.ts +13 -0
- package/dist/agents/communications/identity.js +18 -0
- package/dist/agents/communications/imessageListener.d.ts +41 -0
- package/dist/agents/communications/imessageListener.js +92 -0
- package/dist/agents/communications/inbound.d.ts +63 -0
- package/dist/agents/communications/inbound.js +143 -0
- package/dist/agents/communications/listener.d.ts +36 -0
- package/dist/agents/communications/listener.js +38 -0
- package/dist/agents/communications/photon.d.ts +19 -0
- package/dist/agents/communications/photon.js +38 -0
- package/dist/agents/communications/port.d.ts +27 -0
- package/dist/agents/communications/port.js +6 -0
- package/dist/agents/communications/slack.d.ts +28 -0
- package/dist/agents/communications/slack.js +65 -0
- package/dist/agents/communications/supervisor.d.ts +36 -0
- package/dist/agents/communications/supervisor.js +96 -0
- package/dist/agents/communications/telegram.d.ts +19 -0
- package/dist/agents/communications/telegram.js +52 -0
- package/dist/agents/definitionSummary.d.ts +13 -0
- package/dist/agents/definitionSummary.js +91 -0
- package/dist/agents/delegate.d.ts +3 -0
- package/dist/agents/delegate.js +8 -0
- package/dist/agents/errors.d.ts +10 -0
- package/dist/agents/errors.js +32 -0
- package/dist/agents/guardrails.d.ts +24 -0
- package/dist/agents/guardrails.js +39 -0
- package/dist/agents/historyFit.d.ts +10 -0
- package/dist/agents/historyFit.js +26 -0
- package/dist/agents/hostContext.d.ts +54 -0
- package/dist/agents/hostContext.js +156 -0
- package/dist/agents/ledgers.d.ts +29 -0
- package/dist/agents/ledgers.js +31 -0
- package/dist/agents/lineDiff.d.ts +12 -0
- package/dist/agents/lineDiff.js +46 -0
- package/dist/agents/ndjson.d.ts +9 -0
- package/dist/agents/ndjson.js +47 -0
- package/dist/agents/otlpExport.d.ts +9 -0
- package/dist/agents/otlpExport.js +58 -0
- package/dist/agents/otlpSink.d.ts +7 -0
- package/dist/agents/otlpSink.js +23 -0
- package/dist/agents/policy.d.ts +31 -0
- package/dist/agents/policy.js +84 -0
- package/dist/agents/projectRoot.d.ts +5 -0
- package/dist/agents/projectRoot.js +15 -0
- package/dist/agents/runtime/piRuntime.d.ts +52 -0
- package/dist/agents/runtime/piRuntime.js +474 -0
- package/dist/agents/runtime/types.d.ts +77 -0
- package/dist/agents/runtime/types.js +26 -0
- package/dist/agents/sandbox.d.ts +17 -0
- package/dist/agents/sandbox.js +10 -0
- package/dist/agents/scheduleSource.d.ts +32 -0
- package/dist/agents/scheduleSource.js +100 -0
- package/dist/agents/service.d.ts +298 -0
- package/dist/agents/service.js +1105 -0
- package/dist/agents/sessions.d.ts +38 -0
- package/dist/agents/sessions.js +321 -0
- package/dist/agents/store.d.ts +277 -0
- package/dist/agents/store.js +643 -0
- package/dist/agents/trace.d.ts +27 -0
- package/dist/agents/trace.js +29 -0
- package/dist/agents/turnLifecycle.d.ts +72 -0
- package/dist/agents/turnLifecycle.js +157 -0
- package/dist/agents/webChat/publicChat.d.ts +36 -0
- package/dist/agents/webChat/publicChat.js +290 -0
- package/dist/agents/webChat/rateLimit.d.ts +15 -0
- package/dist/agents/webChat/rateLimit.js +33 -0
- package/dist/agents/webChat/slug.d.ts +2 -0
- package/dist/agents/webChat/slug.js +9 -0
- package/dist/channels/providers/agentmail.js +14 -1
- package/dist/channels/providers/photonImessage.js +36 -0
- package/dist/channels/providers/slack.js +2 -1
- package/dist/channels/providers/telegram.js +2 -1
- package/dist/channels/types.d.ts +27 -0
- package/dist/cli/agentsCommand.d.ts +14 -0
- package/dist/cli/agentsCommand.js +291 -0
- package/dist/cli.js +9 -0
- package/dist/config/browseCatalog.js +4 -11
- package/dist/config/draftPackage.d.ts +1 -0
- package/dist/config/draftPackage.js +4 -0
- package/dist/config/hostConfig.js +9 -0
- package/dist/config/loadAgent.d.ts +266 -0
- package/dist/config/loadAgent.js +374 -0
- package/dist/config/loadPipeline.js +5 -2
- package/dist/config/loadTask.js +34 -1
- package/dist/config/mcpHostCatalog.d.ts +50 -0
- package/dist/config/mcpHostCatalog.js +405 -0
- package/dist/config/mcpOAuth.d.ts +37 -0
- package/dist/config/mcpOAuth.js +263 -0
- package/dist/config/mcpRedaction.d.ts +42 -0
- package/dist/config/mcpRedaction.js +314 -0
- package/dist/config/mcpToolCache.d.ts +20 -0
- package/dist/config/mcpToolCache.js +43 -0
- package/dist/config/mergePipelineIncludes.d.ts +2 -0
- package/dist/config/mergePipelineIncludes.js +25 -0
- package/dist/config/resolveStageMcpServers.d.ts +35 -3
- package/dist/config/resolveStageMcpServers.js +124 -9
- package/dist/config/validateCatalog.d.ts +1 -1
- package/dist/config/validateCatalog.js +22 -1
- package/dist/mcp/agentTools.d.ts +8 -0
- package/dist/mcp/agentTools.js +132 -0
- package/dist/mcp/catalogTools.js +17 -10
- package/dist/mcp/deps.d.ts +6 -0
- package/dist/mcp/pipelineAuthorSupport.d.ts +19 -0
- package/dist/mcp/pipelineAuthorSupport.js +10 -0
- package/dist/mcp/pipelineAuthorTools.d.ts +8 -0
- package/dist/mcp/pipelineAuthorTools.js +109 -0
- package/dist/mcp/server.js +5 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/mcp/triggerTools.js +32 -0
- package/dist/memory/access.d.ts +36 -0
- package/dist/memory/access.js +116 -0
- package/dist/memory/agentIssues.d.ts +3 -0
- package/dist/memory/agentIssues.js +23 -0
- package/dist/memory/bashDeny.d.ts +6 -0
- package/dist/memory/bashDeny.js +35 -0
- package/dist/memory/host.d.ts +51 -0
- package/dist/memory/host.js +394 -0
- package/dist/memory/ids.d.ts +15 -0
- package/dist/memory/ids.js +31 -0
- package/dist/memory/worker.d.ts +1 -0
- package/dist/memory/worker.js +84 -0
- package/dist/models/catalog.d.ts +113 -0
- package/dist/models/catalog.js +238 -0
- package/dist/models/response.d.ts +29 -0
- package/dist/models/response.js +25 -0
- package/dist/operatorAgent/agentAuthorContext.d.ts +17 -0
- package/dist/operatorAgent/agentAuthorContext.js +32 -0
- package/dist/operatorAgent/fakeHost.js +2 -0
- package/dist/operatorAgent/host.js +6 -3
- package/dist/operatorAgent/index.d.ts +4 -0
- package/dist/operatorAgent/index.js +4 -0
- package/dist/operatorAgent/piModel.js +2 -0
- package/dist/operatorAgent/profiles/agentAuthor.d.ts +11 -0
- package/dist/operatorAgent/profiles/agentAuthor.js +192 -0
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -0
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +29 -0
- package/dist/operatorAgent/profiles/workshopAuthor.js +2 -2
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +3 -3
- package/dist/operatorAgent/proposals.d.ts +1 -0
- package/dist/operatorAgent/proposals.js +23 -2
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/preflight/pipelinePreflight.js +1 -0
- package/dist/runstore/createStore.d.ts +2 -0
- package/dist/runstore/createStore.js +8 -0
- package/dist/runstore/overviewSummary.d.ts +56 -0
- package/dist/runstore/overviewSummary.js +134 -0
- package/dist/runstore/port.d.ts +3 -0
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +2 -0
- package/dist/runstore/sqlite/SqliteRunStore.js +18 -0
- package/dist/runstore/sqlite/migrations/013-agents.d.ts +12 -0
- package/dist/runstore/sqlite/migrations/013-agents.js +156 -0
- package/dist/runstore/sqlite/migrations/014-agent-deliveries.d.ts +11 -0
- package/dist/runstore/sqlite/migrations/014-agent-deliveries.js +32 -0
- package/dist/runstore/sqlite/migrations/index.js +4 -0
- package/dist/runtime/gitCheckoutCapability.d.ts +1 -0
- package/dist/runtime/gitCheckoutCapability.js +1 -1
- package/dist/runtime/gitWorktreeCheckout.d.ts +22 -0
- package/dist/runtime/gitWorktreeCheckout.js +120 -0
- package/dist/runtime/sandboxContainer.d.ts +62 -0
- package/dist/runtime/sandboxContainer.js +151 -0
- package/dist/runtime/sandboxDesk.d.ts +28 -0
- package/dist/runtime/sandboxDesk.js +242 -0
- package/dist/runtime/sandboxFiles.d.ts +20 -0
- package/dist/runtime/sandboxFiles.js +150 -0
- package/dist/runtime/stageAttemptBootstrap.js +15 -1
- package/dist/runtime/stageEnvironment.d.ts +2 -0
- package/dist/runtime/stageEnvironment.js +8 -1
- package/dist/runtime/stageProcessLauncher.js +23 -0
- package/dist/runtime/stageRoots.d.ts +9 -0
- package/dist/runtime/stageRoots.js +14 -0
- package/dist/runtime/stageRunner.d.ts +5 -0
- package/dist/runtime/stageRunner.js +38 -4
- package/dist/runtime/stageSandbox.d.ts +16 -0
- package/dist/runtime/stageSandbox.js +54 -0
- package/dist/runtime/stageSecrets.d.ts +6 -1
- package/dist/runtime/stageSecrets.js +34 -1
- package/dist/runtime/stageWorker.js +138 -105
- package/dist/runtime/workspaceBinding.d.ts +2 -1
- package/dist/runtime/workspaceBinding.js +20 -4
- package/dist/server/agentAuthorRoutes.d.ts +5 -0
- package/dist/server/agentAuthorRoutes.js +64 -0
- package/dist/server/agentRoutes.d.ts +5 -0
- package/dist/server/agentRoutes.js +323 -0
- package/dist/server/bootstrap.d.ts +8 -0
- package/dist/server/bootstrap.js +36 -10
- package/dist/server/controlToken.js +8 -0
- package/dist/server/http.d.ts +8 -1
- package/dist/server/http.js +172 -20
- package/dist/server/mcpHost.js +1 -0
- package/dist/server/memoryRoutes.d.ts +5 -0
- package/dist/server/memoryRoutes.js +146 -0
- package/dist/server/projectMcpRoutes.d.ts +1 -0
- package/dist/server/projectMcpRoutes.js +241 -3
- package/dist/toolkit/guard.d.ts +27 -0
- package/dist/toolkit/guard.js +98 -0
- package/dist/toolkit/index.d.ts +48 -0
- package/dist/toolkit/index.js +82 -0
- package/dist/toolkit/meta.d.ts +36 -0
- package/dist/toolkit/meta.js +117 -0
- package/dist/toolkit/profiles.d.ts +13 -0
- package/dist/toolkit/profiles.js +25 -0
- package/dist/toolkit/record.d.ts +15 -0
- package/dist/toolkit/record.js +17 -0
- package/dist/tools/memoryTools.d.ts +95 -0
- package/dist/tools/memoryTools.js +179 -0
- package/dist/types/pipeline.d.ts +3 -0
- package/dist/types/stage.d.ts +2 -0
- package/dist/types/task.d.ts +11 -1
- package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +9 -0
- package/dist/ui/assets/MarkdownText-D7tYaIFO.js +29 -0
- package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +6 -0
- package/dist/ui/assets/Tooltip-DrpoRRNi.js +1 -0
- package/dist/ui/assets/chat-BbLukq9W.js +5 -0
- package/dist/ui/assets/chat-zIZU_bP1.css +2 -0
- package/dist/ui/assets/jsx-runtime-iVoFAvQ_.js +1 -0
- package/dist/ui/assets/{index-Clv4sJpU.css → main-BFo79krC.css} +1 -1
- package/dist/ui/assets/main-CijYMeM0.js +259 -0
- package/dist/ui/chat.html +25 -0
- package/dist/ui/index.html +6 -2
- package/dist/workshop/modelSettings.d.ts +2 -2
- package/dist/workshop/modelSettings.js +5 -11
- package/examples/README.md +1 -0
- package/examples/channels-smoke/README.md +12 -1
- package/examples/github-release/README.md +1 -1
- package/examples/memory/README.md +101 -0
- package/examples/memory/desk-outage.task.yaml +15 -0
- package/examples/memory/desk-refund.task.yaml +15 -0
- package/examples/memory/desk-revisit-outage.task.yaml +11 -0
- package/examples/memory/desk-revisit.pipeline.yaml +123 -0
- package/examples/memory/desk.pipeline.yaml +192 -0
- package/examples/memory/file-card.pipeline.yaml +39 -0
- package/examples/memory/file-ledger.task.yaml +22 -0
- package/examples/memory/file-release.task.yaml +24 -0
- package/examples/memory/file-rich.pipeline.yaml +40 -0
- package/examples/memory/file-ticket.task.yaml +7 -0
- package/examples/memory/file-timeline.task.yaml +28 -0
- package/examples/memory/find-card.pipeline.yaml +46 -0
- package/examples/memory/find-ticket.task.yaml +7 -0
- package/examples/memory/missing.pipeline.yaml +16 -0
- package/examples/memory/probe-bash.task.yaml +3 -0
- package/examples/memory/recall.pipeline.yaml +24 -0
- package/examples/memory/recall.task.yaml +5 -0
- package/examples/memory/remember-ada.task.yaml +6 -0
- package/examples/memory/remember-grace.task.yaml +6 -0
- package/examples/memory/remember.pipeline.yaml +58 -0
- package/examples/memory/sandbox-memory-bash.pipeline.yaml +28 -0
- package/examples/memory/stageflow.yaml +12 -0
- package/examples/memory/update-card.pipeline.yaml +43 -0
- package/examples/memory/update-ledger.task.yaml +23 -0
- package/examples/memory/update-rich.pipeline.yaml +44 -0
- package/examples/memory/update-ticket.task.yaml +7 -0
- package/examples/ship-feature/README.md +15 -0
- package/examples/stage-mcp/README.md +1 -1
- package/package.json +2 -1
- package/dist/ui/assets/index-BOhqnPNg.js +0 -260
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Cron } from "croner";
|
|
2
|
+
export const DEFAULT_AGENT_SCHEDULE_TICK_INTERVAL_MS = 30_000;
|
|
3
|
+
export function agentScheduleTickIntervalMsFromEnv(env = process.env) {
|
|
4
|
+
const raw = env.STAGEFLOW_AGENT_SCHEDULE_TICK_INTERVAL_MS;
|
|
5
|
+
if (raw === undefined || raw.trim() === "")
|
|
6
|
+
return DEFAULT_AGENT_SCHEDULE_TICK_INTERVAL_MS;
|
|
7
|
+
const parsed = Number(raw);
|
|
8
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
9
|
+
return DEFAULT_AGENT_SCHEDULE_TICK_INTERVAL_MS;
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
function computeNextRunAt(schedule, from) {
|
|
13
|
+
const job = new Cron(schedule.cron, schedule.timezone !== undefined ? { timezone: schedule.timezone } : {});
|
|
14
|
+
return job.nextRun(from);
|
|
15
|
+
}
|
|
16
|
+
export class AgentScheduleSource {
|
|
17
|
+
service;
|
|
18
|
+
projectRoot;
|
|
19
|
+
intervalMs;
|
|
20
|
+
now;
|
|
21
|
+
logError;
|
|
22
|
+
interval;
|
|
23
|
+
inFlight = false;
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.service = options.service;
|
|
26
|
+
this.projectRoot = options.projectRoot;
|
|
27
|
+
this.intervalMs = options.intervalMs ?? DEFAULT_AGENT_SCHEDULE_TICK_INTERVAL_MS;
|
|
28
|
+
this.now = options.now ?? (() => new Date());
|
|
29
|
+
this.logError =
|
|
30
|
+
options.logError ??
|
|
31
|
+
((message) => {
|
|
32
|
+
console.error(message);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async start(onFire) {
|
|
36
|
+
if (this.intervalMs <= 0)
|
|
37
|
+
return;
|
|
38
|
+
this.interval = setInterval(() => {
|
|
39
|
+
if (this.inFlight)
|
|
40
|
+
return;
|
|
41
|
+
this.inFlight = true;
|
|
42
|
+
void this.tick(onFire)
|
|
43
|
+
.catch((err) => {
|
|
44
|
+
this.logError(`agent schedule tick failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
})
|
|
46
|
+
.finally(() => {
|
|
47
|
+
this.inFlight = false;
|
|
48
|
+
});
|
|
49
|
+
}, this.intervalMs).unref();
|
|
50
|
+
}
|
|
51
|
+
async stop() {
|
|
52
|
+
if (this.interval !== undefined)
|
|
53
|
+
clearInterval(this.interval);
|
|
54
|
+
this.interval = undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Fire every enabled agent whose stored next run is due, then store the
|
|
58
|
+
* following occurrence. A host that was down past a due time fires once,
|
|
59
|
+
* not once per missed occurrence.
|
|
60
|
+
*/
|
|
61
|
+
async tick(onFire) {
|
|
62
|
+
const now = this.now();
|
|
63
|
+
for (const candidate of await this.service.scheduledAgents(this.projectRoot)) {
|
|
64
|
+
let following;
|
|
65
|
+
try {
|
|
66
|
+
following = computeNextRunAt(candidate.schedule, now);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
this.logError(`invalid schedule for agent "${candidate.agentId}": ${err instanceof Error ? err.message : String(err)}`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const stored = this.service.schedules.nextRun(this.projectRoot, candidate.agentId);
|
|
73
|
+
if (stored === undefined) {
|
|
74
|
+
if (following)
|
|
75
|
+
this.service.schedules.setNextRun(this.projectRoot, candidate.agentId, following.toISOString());
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (Date.parse(stored) > now.getTime()) {
|
|
79
|
+
// A schedule edited to fire sooner must not wait out the old next run.
|
|
80
|
+
if (following && following.getTime() < Date.parse(stored)) {
|
|
81
|
+
this.service.schedules.setNextRun(this.projectRoot, candidate.agentId, following.toISOString());
|
|
82
|
+
}
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
await onFire({
|
|
87
|
+
agentId: candidate.agentId,
|
|
88
|
+
message: candidate.schedule.message ?? "Scheduled check-in.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
this.logError(`scheduled turn failed for agent "${candidate.agentId}": ${err instanceof Error ? err.message : String(err)}`);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
if (following)
|
|
96
|
+
this.service.schedules.setNextRun(this.projectRoot, candidate.agentId, following.toISOString());
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { type AgentDefinition, type AgentIssue } from "../config/loadAgent.js";
|
|
2
|
+
import { type AgentInboundMessage } from "./communications/port.js";
|
|
3
|
+
import { ApprovalBroker } from "./approvalBroker.js";
|
|
4
|
+
import { type DeliveryLedger, type ScheduleLedger } from "./ledgers.js";
|
|
5
|
+
import { type FinishInput } from "./turnLifecycle.js";
|
|
6
|
+
import { type DiffLine } from "./lineDiff.js";
|
|
7
|
+
import { AgentStore, type AgentApproval, type AgentEvalScore, type AgentMessage, type AgentRevision, type AgentRevisionMeta, type AgentSession, type AgentSessionListItem, type AgentDelivery, type AgentSpan, type AgentTurn, type ApprovalActor, type RevisionSource, type SessionQuery, type SessionStats, type SessionStatus } from "./store.js";
|
|
8
|
+
/** Lookups outside the agents directory, used only to produce non-blocking warnings. */
|
|
9
|
+
export type AgentEnvironment = {
|
|
10
|
+
/** Server names in the project's `.mcp.json`, or undefined when there is no usable catalog. */
|
|
11
|
+
mcpServerNames(projectRoot: string): Promise<string[] | undefined>;
|
|
12
|
+
skillNames(projectRoot: string): Promise<string[] | undefined>;
|
|
13
|
+
connectionIds(): Promise<string[] | undefined>;
|
|
14
|
+
/** What a connection talks to (inbox, Photon project), so two connections on one inbox count as one channel. */
|
|
15
|
+
connectionIdentity?(connectionId: string): Promise<string | undefined>;
|
|
16
|
+
/** What the model catalog says about an id, or undefined when it cannot be checked. */
|
|
17
|
+
modelInfo?(id: string): Promise<{
|
|
18
|
+
known: boolean;
|
|
19
|
+
nativeTools: boolean;
|
|
20
|
+
} | undefined>;
|
|
21
|
+
};
|
|
22
|
+
export type AgentSummary = {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
description: string | null;
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
revision: number;
|
|
28
|
+
/** Problems with the file on disk; a non-empty list on a revision-0 agent means it never loaded. */
|
|
29
|
+
issues: AgentIssue[];
|
|
30
|
+
model: AgentDefinition["model"] | null;
|
|
31
|
+
tools: {
|
|
32
|
+
builtin: string[];
|
|
33
|
+
builtinTools: string[];
|
|
34
|
+
mcpServers: string[];
|
|
35
|
+
skills: string[];
|
|
36
|
+
browser: boolean;
|
|
37
|
+
};
|
|
38
|
+
askFirst: string[];
|
|
39
|
+
/** Connection the agent answers on, if any. */
|
|
40
|
+
channelConnection: string | null;
|
|
41
|
+
/** Cron expression when the agent starts sessions on a schedule. */
|
|
42
|
+
scheduleCron: string | null;
|
|
43
|
+
subAgents: string[];
|
|
44
|
+
capture: AgentDefinition["observability"]["capture"] | null;
|
|
45
|
+
/** Path of the public chat page (`/chat/<slug>`) while web chat is switched on and has a link. */
|
|
46
|
+
webChatUrl: string | null;
|
|
47
|
+
stats: SessionStats;
|
|
48
|
+
pendingApprovals: number;
|
|
49
|
+
updatedAt: string;
|
|
50
|
+
};
|
|
51
|
+
export type AgentDetail = {
|
|
52
|
+
agent: AgentSummary;
|
|
53
|
+
definition: AgentDefinition | null;
|
|
54
|
+
yaml: string | null;
|
|
55
|
+
warnings: AgentIssue[];
|
|
56
|
+
};
|
|
57
|
+
export type ValidationResult = {
|
|
58
|
+
definition: AgentDefinition | null;
|
|
59
|
+
issues: AgentIssue[];
|
|
60
|
+
warnings: AgentIssue[];
|
|
61
|
+
yaml: string | null;
|
|
62
|
+
};
|
|
63
|
+
export type AgentSessionDetail = {
|
|
64
|
+
session: AgentSession;
|
|
65
|
+
messages: AgentMessage[];
|
|
66
|
+
turns: AgentTurn[];
|
|
67
|
+
/** Every recorded span, ordered by turn then start time. Empty when capture is off. */
|
|
68
|
+
spans: AgentSpan[];
|
|
69
|
+
approvals: AgentApproval[];
|
|
70
|
+
pendingApproval: AgentApproval | null;
|
|
71
|
+
evalScores: AgentEvalScore[];
|
|
72
|
+
/** Channel replies and how they went, one per turn that had to reach someone. */
|
|
73
|
+
deliveries: AgentDelivery[];
|
|
74
|
+
};
|
|
75
|
+
export type ActiveTurn = {
|
|
76
|
+
session: AgentSession;
|
|
77
|
+
definition: AgentDefinition;
|
|
78
|
+
turn: AgentTurn;
|
|
79
|
+
history: AgentMessage[];
|
|
80
|
+
userMessage: AgentMessage;
|
|
81
|
+
};
|
|
82
|
+
export type ChangeActor = {
|
|
83
|
+
source: RevisionSource;
|
|
84
|
+
author?: string | null;
|
|
85
|
+
};
|
|
86
|
+
export declare class AgentService {
|
|
87
|
+
private readonly store;
|
|
88
|
+
private readonly environment;
|
|
89
|
+
private readonly now;
|
|
90
|
+
private readonly tails;
|
|
91
|
+
/** Wakes a turn paused at an ask-first tool when its approval is decided. */
|
|
92
|
+
readonly approvalBroker: ApprovalBroker;
|
|
93
|
+
/** Owns every legal change of a turn, its session and its approval. */
|
|
94
|
+
private readonly lifecycle;
|
|
95
|
+
/** Reply delivery bookkeeping, for ReplyDelivery. */
|
|
96
|
+
readonly deliveries: DeliveryLedger;
|
|
97
|
+
/** Next-run bookkeeping, for the scheduler. */
|
|
98
|
+
readonly schedules: ScheduleLedger;
|
|
99
|
+
constructor(options: {
|
|
100
|
+
store: AgentStore;
|
|
101
|
+
environment?: AgentEnvironment;
|
|
102
|
+
now?: () => Date; /** How long a file must be unchanged before its stamp is trusted (default 2 s). */
|
|
103
|
+
treeTrustMs?: number;
|
|
104
|
+
});
|
|
105
|
+
/** The service clock, so waits and expiries agree with stored timestamps. */
|
|
106
|
+
clockMs(): number;
|
|
107
|
+
private iso;
|
|
108
|
+
/** Serialize file-and-database work per project so a save and a sync never interleave. */
|
|
109
|
+
private exclusive;
|
|
110
|
+
private dir;
|
|
111
|
+
private file;
|
|
112
|
+
/**
|
|
113
|
+
* What the agents directory looked like at the last full sync, per project: names, sizes and modification times.
|
|
114
|
+
* While it is unchanged (and old enough to trust), a sync is one readdir and one stat per file, with no reads or
|
|
115
|
+
* hashing. Cleared by our own writes and archives.
|
|
116
|
+
*/
|
|
117
|
+
private readonly syncedTree;
|
|
118
|
+
/** A file touched this recently may be edited again within the clock's resolution, so its stamp is not trusted yet. */
|
|
119
|
+
private readonly treeTrustMs;
|
|
120
|
+
private treeStamp;
|
|
121
|
+
/**
|
|
122
|
+
* Bring the database in line with `agents/*.agent.yaml`. Only files whose
|
|
123
|
+
* content hash changed are parsed. An unchanged tree costs a readdir and a
|
|
124
|
+
* stat per file, and writes nothing; a changed or freshly touched one is
|
|
125
|
+
* read and hashed in full.
|
|
126
|
+
*/
|
|
127
|
+
private sync;
|
|
128
|
+
private fullSync;
|
|
129
|
+
private applyFile;
|
|
130
|
+
/** Write the canonical YAML and record the revision in one step. */
|
|
131
|
+
private writeRevision;
|
|
132
|
+
private readonly changeListeners;
|
|
133
|
+
/** Called after an agent is saved, enabled, disabled, restored or archived, so listeners on channels can follow. */
|
|
134
|
+
onChange(listener: () => void): void;
|
|
135
|
+
private notifyChanged;
|
|
136
|
+
private currentRevision;
|
|
137
|
+
private summarize;
|
|
138
|
+
private pendingByAgent;
|
|
139
|
+
list(projectRoot: string): Promise<AgentSummary[]>;
|
|
140
|
+
get(projectRoot: string, agentId: string): Promise<AgentDetail>;
|
|
141
|
+
/** The definition a session is pinned to. */
|
|
142
|
+
definitionAt(projectRoot: string, agentId: string, revision: number): Promise<AgentDefinition>;
|
|
143
|
+
private warningsFor;
|
|
144
|
+
/**
|
|
145
|
+
* Web chat defaults and links: a new agent starts with web chat on, an enabled block without a link
|
|
146
|
+
* gets one, and `slug: ""` asks for a new link (rotate). Previews never mint links.
|
|
147
|
+
*/
|
|
148
|
+
private prepareWebChat;
|
|
149
|
+
/** The enabled agent a public link points at, or null. */
|
|
150
|
+
findWebChatAgent(projectRoot: string, slug: string): Promise<{
|
|
151
|
+
agentId: string;
|
|
152
|
+
definition: AgentDefinition;
|
|
153
|
+
} | null>;
|
|
154
|
+
/** Fills a missing id from the agent's name so callers never have to choose one. */
|
|
155
|
+
private withGeneratedId;
|
|
156
|
+
/** One connection answers for one agent: another agent already on this connection is an error. */
|
|
157
|
+
private channelConflicts;
|
|
158
|
+
validate(projectRoot: string, rawInput: unknown): Promise<ValidationResult>;
|
|
159
|
+
private parseOrThrow;
|
|
160
|
+
create(projectRoot: string, rawInput: unknown, actor: ChangeActor): Promise<AgentDetail>;
|
|
161
|
+
save(projectRoot: string, agentId: string, input: {
|
|
162
|
+
baseRevision: number;
|
|
163
|
+
definition: unknown;
|
|
164
|
+
summary?: string | null;
|
|
165
|
+
}, actor: ChangeActor): Promise<AgentDetail>;
|
|
166
|
+
setEnabled(projectRoot: string, agentId: string, enabled: boolean, actor: ChangeActor): Promise<AgentDetail>;
|
|
167
|
+
private readonly archiveListeners;
|
|
168
|
+
/** Called after an agent is archived with the ids of its sessions, so a runtime can let go of what it holds for them. */
|
|
169
|
+
onArchived(listener: (agentId: string, sessionIds: string[]) => void): void;
|
|
170
|
+
/** Remove the file; history stays readable (R5). */
|
|
171
|
+
archive(projectRoot: string, agentId: string): Promise<void>;
|
|
172
|
+
listRevisions(projectRoot: string, agentId: string): Promise<AgentRevisionMeta[]>;
|
|
173
|
+
getRevision(projectRoot: string, agentId: string, revision: number): Promise<AgentRevision>;
|
|
174
|
+
diffRevisions(projectRoot: string, agentId: string, from: number, to: number): Promise<DiffLine[]>;
|
|
175
|
+
/** Re-save an old revision as the newest one. Enabled state stays as it is now. */
|
|
176
|
+
restore(projectRoot: string, agentId: string, input: {
|
|
177
|
+
revision: number;
|
|
178
|
+
baseRevision: number;
|
|
179
|
+
}, actor: ChangeActor): Promise<AgentDetail>;
|
|
180
|
+
openSession(projectRoot: string, agentId: string, input: {
|
|
181
|
+
source: string;
|
|
182
|
+
sourceRef?: string | null;
|
|
183
|
+
threadKey?: string | null;
|
|
184
|
+
title?: string | null;
|
|
185
|
+
}): Promise<AgentSession>;
|
|
186
|
+
/** Id of the session's pending approval, if a turn is waiting on a person. */
|
|
187
|
+
pendingApprovalFor(_projectRoot: string, sessionId: string): string | null;
|
|
188
|
+
listSessionsForRef(projectRoot: string, agentId: string, source: string, sourceRef: string, limit: number): AgentSession[];
|
|
189
|
+
private sessionInProject;
|
|
190
|
+
getSession(projectRoot: string, sessionId: string): Promise<AgentSessionDetail>;
|
|
191
|
+
listSessions(projectRoot: string, agentId: string, query: SessionQuery): Promise<{
|
|
192
|
+
sessions: AgentSessionListItem[];
|
|
193
|
+
nextCursor: string | null;
|
|
194
|
+
stats: SessionStats;
|
|
195
|
+
}>;
|
|
196
|
+
/** Sessions of every agent in the project (or of one, when `agentId` is given), newest first, with matching stats. */
|
|
197
|
+
listAllSessions(projectRoot: string, query: SessionQuery, agentId?: string): Promise<{
|
|
198
|
+
sessions: AgentSessionListItem[];
|
|
199
|
+
nextCursor: string | null;
|
|
200
|
+
stats: SessionStats;
|
|
201
|
+
}>;
|
|
202
|
+
listSpans(projectRoot: string, sessionId: string): AgentSpan[];
|
|
203
|
+
/** OTLP/JSON for every turn of a session (what "Export session traces" downloads). */
|
|
204
|
+
exportSessionOtlp(projectRoot: string, sessionId: string): Record<string, unknown>;
|
|
205
|
+
/** OTLP/JSON for one finished turn, for live export to a collector. */
|
|
206
|
+
exportTurnOtlp(projectRoot: string, turnId: string): Record<string, unknown>;
|
|
207
|
+
/**
|
|
208
|
+
* Start a turn on a session's pinned revision: records the user message and
|
|
209
|
+
* marks the session running. The live agent state (enabled, not archived)
|
|
210
|
+
* gates new turns; the pinned revision supplies the configuration.
|
|
211
|
+
*/
|
|
212
|
+
beginTurn(projectRoot: string, sessionId: string, input: {
|
|
213
|
+
text: string;
|
|
214
|
+
author?: string | null;
|
|
215
|
+
resumeTurnId?: string;
|
|
216
|
+
}): Promise<ActiveTurn>;
|
|
217
|
+
/** Session limits (`limits` in the pinned revision) are checked before each new turn. */
|
|
218
|
+
private assertWithinLimits;
|
|
219
|
+
/**
|
|
220
|
+
* A turn is about to pause for a person. Returns "waiting" once it is parked, or the approval's outcome when it was
|
|
221
|
+
* already decided in between (nothing to wait for), or "inactive" when the turn is no longer running.
|
|
222
|
+
*/
|
|
223
|
+
waitOnApproval(projectRoot: string, turnId: string, approvalId: string): Promise<"waiting" | "approved" | "denied" | "expired" | "inactive">;
|
|
224
|
+
/** The wait is over (decided, expired): the turn runs again. */
|
|
225
|
+
resumeTurn(projectRoot: string, turnId: string): Promise<void>;
|
|
226
|
+
/** A stopped turn leaves its ask-first approval behind; close it so it cannot be approved later. */
|
|
227
|
+
closeApproval(projectRoot: string, approvalId: string): Promise<void>;
|
|
228
|
+
/**
|
|
229
|
+
* End a turn. Guarded: a turn that is already over is left as it is (the session detail is returned unchanged), so a
|
|
230
|
+
* late failure handler cannot rewrite a finished outcome.
|
|
231
|
+
*/
|
|
232
|
+
completeTurn(projectRoot: string, turnId: string, input: {
|
|
233
|
+
status: FinishInput["status"];
|
|
234
|
+
assistantText?: string;
|
|
235
|
+
errorCode?: string | null;
|
|
236
|
+
usage?: {
|
|
237
|
+
inputTokens?: number;
|
|
238
|
+
outputTokens?: number;
|
|
239
|
+
};
|
|
240
|
+
costUsd?: number | null;
|
|
241
|
+
evalScores?: Array<{
|
|
242
|
+
metric: string;
|
|
243
|
+
score: number;
|
|
244
|
+
}>;
|
|
245
|
+
sessionStatus?: SessionStatus;
|
|
246
|
+
}): Promise<AgentSessionDetail>;
|
|
247
|
+
recordSpan(projectRoot: string, span: AgentSpan): void;
|
|
248
|
+
/** Called at host start: turns that were running when the host stopped can't resume. */
|
|
249
|
+
private interrupted;
|
|
250
|
+
recoverInterruptedTurns(): number;
|
|
251
|
+
/**
|
|
252
|
+
* Turns a restart cut off on an always-on agent, on a channel where a reply goes back to the sender's own handle
|
|
253
|
+
* (iMessage). Each is retried once; the person's message is not asked again.
|
|
254
|
+
*/
|
|
255
|
+
resumableTurns(projectRoot: string): Promise<Array<{
|
|
256
|
+
agentId: string;
|
|
257
|
+
sessionId: string;
|
|
258
|
+
turnId: string;
|
|
259
|
+
text: string;
|
|
260
|
+
from: string;
|
|
261
|
+
connectionId: string;
|
|
262
|
+
provider: string;
|
|
263
|
+
threadId: string;
|
|
264
|
+
}>>;
|
|
265
|
+
/** Sends a restart cut off may or may not have arrived; they wait for a person. */
|
|
266
|
+
settleInterruptedDeliveries(): string[];
|
|
267
|
+
/** A reply that did not get through makes its turn a failure; one that finally does puts it right. */
|
|
268
|
+
setReplyDelivered(turnId: string, delivered: boolean): void;
|
|
269
|
+
latestUndelivered(projectRoot: string, agentId: string): AgentDelivery | undefined;
|
|
270
|
+
private expireApprovals;
|
|
271
|
+
requestApproval(projectRoot: string, sessionId: string, input: {
|
|
272
|
+
tool: string;
|
|
273
|
+
payload: Record<string, unknown>;
|
|
274
|
+
turnId?: string | null;
|
|
275
|
+
}): Promise<AgentApproval>;
|
|
276
|
+
decideApproval(projectRoot: string, sessionId: string, decision: "approve" | "deny", actor: ApprovalActor): Promise<AgentApproval>;
|
|
277
|
+
pendingApprovals(projectRoot: string): Promise<Array<AgentApproval & {
|
|
278
|
+
agentId: string;
|
|
279
|
+
}>>;
|
|
280
|
+
receive(projectRoot: string, message: AgentInboundMessage): Promise<{
|
|
281
|
+
agentId: string;
|
|
282
|
+
sessionId: string;
|
|
283
|
+
duplicate: boolean;
|
|
284
|
+
}>;
|
|
285
|
+
/**
|
|
286
|
+
* At-most-once outbound send keyed by operation. A send whose outcome is
|
|
287
|
+
* unknown (crash between submit and record) is never retried automatically.
|
|
288
|
+
*/
|
|
289
|
+
sendOutbound(projectRoot: string, sessionId: string, operationKey: string, submit: () => Promise<void>): Promise<{
|
|
290
|
+
state: "submitted";
|
|
291
|
+
resent: boolean;
|
|
292
|
+
}>;
|
|
293
|
+
scheduledAgents(projectRoot: string): Promise<Array<{
|
|
294
|
+
agentId: string;
|
|
295
|
+
schedule: NonNullable<AgentDefinition["schedule"]>;
|
|
296
|
+
}>>;
|
|
297
|
+
}
|
|
298
|
+
export declare function hashApprovalPayload(payload: Record<string, unknown>): string;
|