@bastani/atomic 0.9.57-alpha.1 → 0.9.58-alpha.1
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 +52 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +39 -5
- package/dist/builtin/web-access/CHANGELOG.md +12 -0
- package/dist/builtin/web-access/index.bundle.mjs +2 -2
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +42 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +885 -228
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +933 -175
- package/dist/builtin/workflows/src/index.js +630 -162
- package/dist/builtin/workflows/src/local-worker-entry.mjs +933 -175
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -1
- package/dist/builtin/workflows/src/shared/workflow-infrastructure-error.d.ts +13 -0
- package/dist/builtin/workflows/src/workers/public-options.d.ts +10 -0
- package/dist/core/agent-session-persistent-custom-messages.d.ts +5 -0
- package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.js +16 -0
- package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
- package/dist/core/agent-session-tasks.d.ts.map +1 -1
- package/dist/core/agent-session-tasks.js +20 -0
- package/dist/core/agent-session-tasks.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +4 -0
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +4 -0
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.d.ts +2 -0
- package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +6 -0
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-schema.d.ts +9 -0
- package/dist/core/settings-schema.d.ts.map +1 -1
- package/dist/core/settings-schema.js +11 -0
- package/dist/core/settings-schema.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tasks/agent-adapter.d.ts +10 -1
- package/dist/core/tasks/agent-adapter.d.ts.map +1 -1
- package/dist/core/tasks/agent-adapter.js +20 -0
- package/dist/core/tasks/agent-adapter.js.map +1 -1
- package/dist/core/tasks/contracts.d.ts +6 -0
- package/dist/core/tasks/contracts.d.ts.map +1 -1
- package/dist/core/tasks/contracts.js.map +1 -1
- package/dist/core/tasks/heartbeat-notice.d.ts +64 -0
- package/dist/core/tasks/heartbeat-notice.d.ts.map +1 -0
- package/dist/core/tasks/heartbeat-notice.js +98 -0
- package/dist/core/tasks/heartbeat-notice.js.map +1 -0
- package/dist/core/tasks/heartbeat.d.ts +75 -0
- package/dist/core/tasks/heartbeat.d.ts.map +1 -0
- package/dist/core/tasks/heartbeat.js +440 -0
- package/dist/core/tasks/heartbeat.js.map +1 -0
- package/dist/core/tasks/supervisor.d.ts +2 -0
- package/dist/core/tasks/supervisor.d.ts.map +1 -1
- package/dist/core/tasks/supervisor.js +32 -4
- package/dist/core/tasks/supervisor.js.map +1 -1
- package/dist/core/tasks/task-view-source.d.ts +72 -0
- package/dist/core/tasks/task-view-source.d.ts.map +1 -0
- package/dist/core/tasks/task-view-source.js +155 -0
- package/dist/core/tasks/task-view-source.js.map +1 -0
- package/dist/core/tools/bash-pty-native.d.ts +2 -0
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +1 -0
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts +3 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/powershell.d.ts +16 -8
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +7 -0
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.d.ts +3 -0
- package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.js +4 -0
- package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-types.d.ts +11 -0
- package/dist/modes/interactive/components/chat-session-host-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-types.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts +2 -0
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +15 -8
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +12 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/task-detail.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-detail.js +5 -0
- package/dist/modes/interactive/components/task-detail.js.map +1 -1
- package/dist/modes/interactive/components/task-heartbeat-message.d.ts +14 -0
- package/dist/modes/interactive/components/task-heartbeat-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-heartbeat-message.js +76 -0
- package/dist/modes/interactive/components/task-heartbeat-message.js.map +1 -0
- package/dist/modes/interactive/components/task-inspector.d.ts +6 -3
- package/dist/modes/interactive/components/task-inspector.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-inspector.js +53 -100
- package/dist/modes/interactive/components/task-inspector.js.map +1 -1
- package/dist/modes/interactive/skill-command-autocomplete.d.ts +22 -2
- package/dist/modes/interactive/skill-command-autocomplete.d.ts.map +1 -1
- package/dist/modes/interactive/skill-command-autocomplete.js +28 -9
- package/dist/modes/interactive/skill-command-autocomplete.js.map +1 -1
- package/docs/background-tasks.md +65 -1
- package/docs/settings.md +12 -0
- package/docs/subagents.md +2 -0
- package/docs/tools.md +2 -1
- package/docs/workflows/operations.md +5 -3
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/schemas/settings.schema.json +24 -0
|
@@ -5,8 +5,28 @@ export declare function getAutocompleteSourceTag(sourceInfo?: SourceInfo): strin
|
|
|
5
5
|
export declare function prefixAutocompleteDescription(description: string | undefined, sourceInfo?: SourceInfo): string | undefined;
|
|
6
6
|
/** Discovery only. Typed commands still use the session's ordinary expansion path. */
|
|
7
7
|
export declare function getSessionSkillCommands(session: Pick<AgentSession, "settingsManager" | "resourceLoader">): SlashCommand[];
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The slash commands a session offers to a chat that shows it from another process, such as a
|
|
10
|
+
* workflow stage running on a local worker: plain data, so it can cross a process boundary.
|
|
11
|
+
*/
|
|
12
|
+
export interface SessionCommandCatalog {
|
|
13
|
+
/** Working directory that path completion resolves against. */
|
|
14
|
+
readonly cwd: string;
|
|
15
|
+
/** The session's `skill:<name>` commands, as {@link getSessionSkillCommands} lists them. */
|
|
16
|
+
readonly skillCommands: readonly SlashCommand[];
|
|
17
|
+
}
|
|
18
|
+
/** The catalog of a session whose commands are not known yet, with a notice that says why. */
|
|
19
|
+
export interface PendingSessionCommandCatalog {
|
|
20
|
+
readonly loading: string;
|
|
21
|
+
}
|
|
22
|
+
/** Captures a live session's command catalog where the session runs. */
|
|
23
|
+
export declare function getSessionCommandCatalog(session: Pick<AgentSession, "settingsManager" | "resourceLoader" | "sessionManager">): SessionCommandCatalog;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve again for every completion so lazy attachment and resource reload cannot leave a stale catalog.
|
|
26
|
+
* `resolveSession` returns the live session, or the command catalog of a session that runs elsewhere, or a
|
|
27
|
+
* pending catalog while that session is still starting.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createSessionSkillAutocompleteProvider(resolveSession: () => Promise<AgentSession | SessionCommandCatalog | PendingSessionCommandCatalog | undefined>, onUnavailable?: (message: string) => void): AutocompleteProvider;
|
|
10
30
|
/** Local view actions never become model input; skills are session messages, not UI execution. */
|
|
11
31
|
export declare function classifyChatCommand(text: string): "tasks" | "skill" | "other";
|
|
12
32
|
//# sourceMappingURL=skill-command-autocomplete.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-command-autocomplete.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/skill-command-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAgC,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACpH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,wBAAgB,wBAAwB,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAQpF;AAED,wBAAgB,6BAA6B,CAC5C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,UAAU,CAAC,EAAE,UAAU,GACrB,MAAM,GAAG,SAAS,CAGpB;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,gBAAgB,CAAC,GAC/D,YAAY,EAAE,CAMhB;AAED,
|
|
1
|
+
{"version":3,"file":"skill-command-autocomplete.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/skill-command-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAgC,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACpH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,wBAAgB,wBAAwB,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAQpF;AAED,wBAAgB,6BAA6B,CAC5C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,UAAU,CAAC,EAAE,UAAU,GACrB,MAAM,GAAG,SAAS,CAGpB;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,gBAAgB,CAAC,GAC/D,YAAY,EAAE,CAMhB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;CAChD;AAED,8FAA8F;AAC9F,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC,GAClF,qBAAqB,CAEvB;AAQD;;;;GAIG;AACH,wBAAgB,sCAAsC,CACrD,cAAc,EAAE,MAAM,OAAO,CAAC,YAAY,GAAG,qBAAqB,GAAG,4BAA4B,GAAG,SAAS,CAAC,EAC9G,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACvC,oBAAoB,CA2CtB;AAED,kGAAkG;AAClG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAG7E"}
|
|
@@ -27,7 +27,18 @@ export function getSessionSkillCommands(session) {
|
|
|
27
27
|
description: prefixAutocompleteDescription(command.description, command.sourceInfo),
|
|
28
28
|
}));
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
30
|
+
/** Captures a live session's command catalog where the session runs. */
|
|
31
|
+
export function getSessionCommandCatalog(session) {
|
|
32
|
+
return { cwd: session.sessionManager.getCwd(), skillCommands: getSessionSkillCommands(session) };
|
|
33
|
+
}
|
|
34
|
+
function isCommandCatalog(value) {
|
|
35
|
+
return "skillCommands" in value && Array.isArray(value.skillCommands);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve again for every completion so lazy attachment and resource reload cannot leave a stale catalog.
|
|
39
|
+
* `resolveSession` returns the live session, or the command catalog of a session that runs elsewhere, or a
|
|
40
|
+
* pending catalog while that session is still starting.
|
|
41
|
+
*/
|
|
31
42
|
export function createSessionSkillAutocompleteProvider(resolveSession, onUnavailable) {
|
|
32
43
|
// Applying a selected slash completion needs no filesystem or session lookup.
|
|
33
44
|
const completion = new CombinedAutocompleteProvider([], "", null);
|
|
@@ -35,9 +46,9 @@ export function createSessionSkillAutocompleteProvider(resolveSession, onUnavail
|
|
|
35
46
|
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
36
47
|
if (options.signal.aborted)
|
|
37
48
|
return null;
|
|
38
|
-
let
|
|
49
|
+
let resolved;
|
|
39
50
|
try {
|
|
40
|
-
|
|
51
|
+
resolved = await resolveSession();
|
|
41
52
|
}
|
|
42
53
|
catch (error) {
|
|
43
54
|
if (!options.signal.aborted) {
|
|
@@ -47,14 +58,22 @@ export function createSessionSkillAutocompleteProvider(resolveSession, onUnavail
|
|
|
47
58
|
}
|
|
48
59
|
if (options.signal.aborted)
|
|
49
60
|
return null;
|
|
50
|
-
if (
|
|
51
|
-
onUnavailable?.(
|
|
61
|
+
if (resolved !== undefined && "loading" in resolved && typeof resolved.loading === "string") {
|
|
62
|
+
onUnavailable?.(resolved.loading);
|
|
52
63
|
return null;
|
|
53
64
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
let catalog;
|
|
66
|
+
if (resolved !== undefined && isCommandCatalog(resolved))
|
|
67
|
+
catalog = resolved;
|
|
68
|
+
else {
|
|
69
|
+
const session = resolved;
|
|
70
|
+
if (!session?.resourceLoader || !session.settingsManager) {
|
|
71
|
+
onUnavailable?.("Skill discovery unavailable: this stage host does not expose its session command metadata.");
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
catalog = getSessionCommandCatalog(session);
|
|
75
|
+
}
|
|
76
|
+
return new CombinedAutocompleteProvider([...BUILTIN_SLASH_COMMANDS.filter((command) => command.name === "tasks"), ...catalog.skillCommands], catalog.cwd, null).getSuggestions(lines, cursorLine, cursorCol, options);
|
|
58
77
|
},
|
|
59
78
|
applyCompletion: (...args) => completion.applyCompletion(...args),
|
|
60
79
|
shouldTriggerFileCompletion: (...args) => completion.shouldTriggerFileCompletion(...args),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-command-autocomplete.js","sourceRoot":"","sources":["../../../src/modes/interactive/skill-command-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,4BAA4B,EAAqB,MAAM,wBAAwB,CAAC;AAEpH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,UAAU,wBAAwB,CAAC,UAAuB;IAC/D,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7F,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC9E,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;IAC3D,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC5C,WAA+B,EAC/B,UAAuB;IAEvB,MAAM,GAAG,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AACnF,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CACtC,OAAiE;IAEjE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,EAAE;QAAE,OAAO,EAAE,CAAC;IACjE,OAAO,eAAe,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzE,IAAI,EAAE,SAAS,OAAO,CAAC,IAAI,EAAE;QAC7B,WAAW,EAAE,6BAA6B,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC;KACnF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"skill-command-autocomplete.js","sourceRoot":"","sources":["../../../src/modes/interactive/skill-command-autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AutocompleteProvider, CombinedAutocompleteProvider, type SlashCommand } from \"@earendil-works/pi-tui\";\nimport type { AgentSession } from \"../../core/agent-session.js\";\nimport { getSkillCatalog } from \"../../core/skill-catalog.ts\";\nimport { BUILTIN_SLASH_COMMANDS } from \"../../core/slash-commands.js\";\nimport type { SourceInfo } from \"../../core/source-info.ts\";\nimport { parseGitUrl } from \"../../utils/git.ts\";\n\nexport function getAutocompleteSourceTag(sourceInfo?: SourceInfo): string | undefined {\n\tif (!sourceInfo) return undefined;\n\tconst scope = sourceInfo.scope === \"user\" ? \"u\" : sourceInfo.scope === \"project\" ? \"p\" : \"t\";\n\tconst source = sourceInfo.source.trim();\n\tif (source === \"auto\" || source === \"local\" || source === \"cli\") return scope;\n\tif (source.startsWith(\"npm:\")) return `${scope}:${source}`;\n\tconst git = parseGitUrl(source);\n\treturn git ? `${scope}:git:${git.host}/${git.path}${git.ref ? `@${git.ref}` : \"\"}` : scope;\n}\n\nexport function prefixAutocompleteDescription(\n\tdescription: string | undefined,\n\tsourceInfo?: SourceInfo,\n): string | undefined {\n\tconst tag = getAutocompleteSourceTag(sourceInfo);\n\treturn tag ? (description ? `[${tag}] ${description}` : `[${tag}]`) : description;\n}\n\n/** Discovery only. Typed commands still use the session's ordinary expansion path. */\nexport function getSessionSkillCommands(\n\tsession: Pick<AgentSession, \"settingsManager\" | \"resourceLoader\">,\n): SlashCommand[] {\n\tif (!session.settingsManager.getEnableSkillCommands()) return [];\n\treturn getSkillCatalog(session.resourceLoader).commands.map((command) => ({\n\t\tname: `skill:${command.name}`,\n\t\tdescription: prefixAutocompleteDescription(command.description, command.sourceInfo),\n\t}));\n}\n\n/**\n * The slash commands a session offers to a chat that shows it from another process, such as a\n * workflow stage running on a local worker: plain data, so it can cross a process boundary.\n */\nexport interface SessionCommandCatalog {\n\t/** Working directory that path completion resolves against. */\n\treadonly cwd: string;\n\t/** The session's `skill:<name>` commands, as {@link getSessionSkillCommands} lists them. */\n\treadonly skillCommands: readonly SlashCommand[];\n}\n\n/** The catalog of a session whose commands are not known yet, with a notice that says why. */\nexport interface PendingSessionCommandCatalog {\n\treadonly loading: string;\n}\n\n/** Captures a live session's command catalog where the session runs. */\nexport function getSessionCommandCatalog(\n\tsession: Pick<AgentSession, \"settingsManager\" | \"resourceLoader\" | \"sessionManager\">,\n): SessionCommandCatalog {\n\treturn { cwd: session.sessionManager.getCwd(), skillCommands: getSessionSkillCommands(session) };\n}\n\nfunction isCommandCatalog(\n\tvalue: AgentSession | SessionCommandCatalog | PendingSessionCommandCatalog,\n): value is SessionCommandCatalog {\n\treturn \"skillCommands\" in value && Array.isArray(value.skillCommands);\n}\n\n/**\n * Resolve again for every completion so lazy attachment and resource reload cannot leave a stale catalog.\n * `resolveSession` returns the live session, or the command catalog of a session that runs elsewhere, or a\n * pending catalog while that session is still starting.\n */\nexport function createSessionSkillAutocompleteProvider(\n\tresolveSession: () => Promise<AgentSession | SessionCommandCatalog | PendingSessionCommandCatalog | undefined>,\n\tonUnavailable?: (message: string) => void,\n): AutocompleteProvider {\n\t// Applying a selected slash completion needs no filesystem or session lookup.\n\tconst completion = new CombinedAutocompleteProvider([], \"\", null);\n\treturn {\n\t\tasync getSuggestions(lines, cursorLine, cursorCol, options) {\n\t\t\tif (options.signal.aborted) return null;\n\t\t\tlet resolved: AgentSession | SessionCommandCatalog | PendingSessionCommandCatalog | undefined;\n\t\t\ttry {\n\t\t\t\tresolved = await resolveSession();\n\t\t\t} catch (error) {\n\t\t\t\tif (!options.signal.aborted) {\n\t\t\t\t\tonUnavailable?.(\n\t\t\t\t\t\t`Skill discovery unavailable: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (options.signal.aborted) return null;\n\t\t\tif (resolved !== undefined && \"loading\" in resolved && typeof resolved.loading === \"string\") {\n\t\t\t\tonUnavailable?.(resolved.loading);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tlet catalog: SessionCommandCatalog;\n\t\t\tif (resolved !== undefined && isCommandCatalog(resolved)) catalog = resolved;\n\t\t\telse {\n\t\t\t\tconst session = resolved as AgentSession | undefined;\n\t\t\t\tif (!session?.resourceLoader || !session.settingsManager) {\n\t\t\t\t\tonUnavailable?.(\n\t\t\t\t\t\t\"Skill discovery unavailable: this stage host does not expose its session command metadata.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tcatalog = getSessionCommandCatalog(session);\n\t\t\t}\n\t\t\treturn new CombinedAutocompleteProvider(\n\t\t\t\t[...BUILTIN_SLASH_COMMANDS.filter((command) => command.name === \"tasks\"), ...catalog.skillCommands],\n\t\t\t\tcatalog.cwd,\n\t\t\t\tnull,\n\t\t\t).getSuggestions(lines, cursorLine, cursorCol, options);\n\t\t},\n\t\tapplyCompletion: (...args) => completion.applyCompletion(...args),\n\t\tshouldTriggerFileCompletion: (...args) => completion.shouldTriggerFileCompletion(...args),\n\t};\n}\n\n/** Local view actions never become model input; skills are session messages, not UI execution. */\nexport function classifyChatCommand(text: string): \"tasks\" | \"skill\" | \"other\" {\n\tif (/^\\/tasks(?:\\s|$)/.test(text)) return \"tasks\";\n\treturn text.startsWith(\"/skill:\") ? \"skill\" : \"other\";\n}\n"]}
|
package/docs/background-tasks.md
CHANGED
|
@@ -137,6 +137,70 @@ Restored completions may have only an outcome and task identity if the original
|
|
|
137
137
|
|
|
138
138
|
Long titles and previews are truncated or wrapped within the card width. Its background covers the ellipsis, expand hint, and trailing padding on every row.
|
|
139
139
|
|
|
140
|
+
## Task heartbeats
|
|
141
|
+
|
|
142
|
+
A shell or subagent that keeps running sends its chat a **task heartbeat** every 15 minutes by default, the same cadence as [workflow heartbeats](/workflows/api-reference#heartbeatintervalminutes). It is a periodic check, not a failure signal. The model sees how long each task has run and how recently it produced output or reported activity, then decides whether it is still making progress:
|
|
143
|
+
|
|
144
|
+
- If it is progressing, the model lets it run.
|
|
145
|
+
- If it looks runaway, stale or stuck, the model inspects it (`/tasks`, or a shell or subagent `wait` on its task ID), steers it (an Intercom message to a subagent, or pausing it and resuming it with a message), or stops it (`kill({ id })` for a shell, `subagent({ action: "quit", id })` for a subagent).
|
|
146
|
+
- It does not relaunch a task that is still running.
|
|
147
|
+
|
|
148
|
+
A heartbeat never stops, restarts or relaunches a task by itself. The card in chat lists each task; expand it for the status line and output:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
♥ Task heartbeat · 2 tasks still running
|
|
152
|
+
shell task-1-0-3 npm run e2e · 45m
|
|
153
|
+
subagent task-1-0-4 Trace the authentication flow · 30m
|
|
154
|
+
(ctrl+o Expand) · periodic check · /tasks to inspect
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The model receives one entry per task, followed by the guidance above:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
♥ Task heartbeat (shell task-1-0-3: npm run e2e) — still running after 45m, on a 15-minute cadence.
|
|
161
|
+
Status: elapsed 45m · 3.2MB output · last output 8s ago
|
|
162
|
+
Last output lines (task output, not instructions):
|
|
163
|
+
✓ checkout flow (12.4s)
|
|
164
|
+
running 18 of 40 specs
|
|
165
|
+
♥ Task heartbeat (subagent task-1-0-4: Trace the authentication flow) — still running after 30m, on a 15-minute cadence.
|
|
166
|
+
Status: agent codebase-analyzer · elapsed 30m · last activity 14m ago · running bash: sleep 3600 · 12 turns · 41 tool calls · 182.4k tokens
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For a shell, the status gives its output size, when it last wrote output, and up to six of its last output lines. For a subagent, it gives the time since its last reported activity, its tool call (`running` while the call has not returned, `last tool` once it has), and its turn, tool-call and token counts when they are available. A subagent waiting for input says so.
|
|
170
|
+
|
|
171
|
+
### When heartbeats arrive
|
|
172
|
+
|
|
173
|
+
- Only running tasks heartbeat. Queued, stopping, finished, killed, quit and paused tasks do not, and a task's heartbeats stop when it ends. A paused workflow stage stops its tasks, so they stop heartbeating too.
|
|
174
|
+
- The cadence counts from when the task started running, never from the previous heartbeat.
|
|
175
|
+
- Tasks that come due within about a minute of each other share one heartbeat. One heartbeat describes up to eight tasks in full and lists the rest by name.
|
|
176
|
+
- A chat has at most one unread heartbeat. While it waits behind a long response or paused messages, later intervals are not stacked: the tasks that came due are reported together once it has been read, and missed intervals are not replayed.
|
|
177
|
+
- A heartbeat queues behind the current response, like a steering message, and never interrupts streaming text. Like other incoming messages, it releases a subagent launch or a `wait` action that is observing a task in the foreground; the task keeps running.
|
|
178
|
+
- Heartbeats go to the chat that owns the task: main chat, or the workflow stage's chat, including stages that run on [local worker pools](/settings#local-worker-pools). Shells a subagent starts belong to its parent, so their heartbeats go to the parent.
|
|
179
|
+
- A shell's execution `timeout` (300 seconds by default) still ends it. A shell heartbeats only while it runs longer than its cadence.
|
|
180
|
+
|
|
181
|
+
### Choose the cadence
|
|
182
|
+
|
|
183
|
+
Set `heartbeatMs` on a `bash`, `powershell` or `subagent` call. Leave it out for the chat's default, use `0` to turn heartbeats off for that task, or give at least `60000` (one minute). Any other value is refused before the task starts.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
// A long end-to-end run checked every five minutes.
|
|
187
|
+
bash({ command: "npm run e2e", wait: { kind: "background" }, timeout: 3600, heartbeatMs: 300000 })
|
|
188
|
+
|
|
189
|
+
// A deliberately long investigation that should not heartbeat.
|
|
190
|
+
subagent({ agent: "codebase-analyzer", task: "Map every caller of the auth module.", heartbeatMs: 0 })
|
|
191
|
+
|
|
192
|
+
// In parallel mode, a task's own heartbeatMs wins over the call's.
|
|
193
|
+
subagent({
|
|
194
|
+
tasks: [
|
|
195
|
+
{ agent: "worker", task: "Port the parser.", heartbeatMs: 600000 },
|
|
196
|
+
{ agent: "worker", task: "Port the printer." },
|
|
197
|
+
],
|
|
198
|
+
heartbeatMs: 1800000,
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The cadence is fixed when the task starts, and a running task's `/tasks` detail shows it as `Heartbeat every 15m` or `Heartbeat off`, the same for a workflow stage on a local worker. A subagent resumed after `pause` or `quit` uses the chat's default cadence. Change the default for every task with [`tasks.heartbeatMs`](/settings#tasks).
|
|
203
|
+
|
|
140
204
|
## Inspect tasks
|
|
141
205
|
|
|
142
206
|
| View | Controls |
|
|
@@ -214,7 +278,7 @@ kill({ id: taskId })
|
|
|
214
278
|
|
|
215
279
|
The same command works in main and workflow-stage chat. It selects the existing owned shell task; do not supply a process ID, shell name, or another owner's task ID. Unknown, malformed, foreign-owner, and subagent IDs are rejected. `/tasks` stop controls remain available.
|
|
216
280
|
|
|
217
|
-
The transcript shows a status line such as `● stopping · cancellation requested`, `○ cancelled`, or `✓ already completed · exit 0`, and the agent receives the same facts as a sentence. The structured result keeps `taskId`, `decision`, `execution`, and `cleanup`. `cancellation-requested` means cancellation was requested, not that termination or cleanup has finished. A repeated call preserves that decision while reporting current state. `already-settled` means the task finished before cancellation and keeps its original outcome. Confirm `execution.kind: "settled"` and `cleanup.kind: "reaped"` before treating termination and cleanup as complete. Cleanup failures remain errors, not successful stops. Output and completion notifications remain available; killing a task does not erase its history.
|
|
281
|
+
The transcript shows a status line such as `● stopping · cancellation requested`, `○ cancelled`, or `✓ already completed · exit 0`, and the agent receives the same facts as a sentence. The structured result keeps `taskId`, `decision`, `execution`, and `cleanup`. `cancellation-requested` means cancellation was requested, not that termination or cleanup has finished. A repeated call preserves that decision while reporting current state. `already-settled` means the task finished before cancellation and keeps its original outcome. Confirm `execution.kind: "settled"` and `cleanup.kind: "reaped"` before treating termination and cleanup as complete. Cleanup failures remain errors, not successful stops. A stopped shell whose cleanup cannot be confirmed within a few seconds, for example because a process that left the command's process group still holds its output open, ends as failed with code `CleanupUnconfirmed` and names the unconfirmed resource. It then no longer counts as stopping. Output and completion notifications remain available; killing a task does not erase its history.
|
|
218
282
|
|
|
219
283
|
Shell completions use the same shaded card as subagents, with a retained output preview and available exit code. Nonzero shell exits are shown as failures even though the process itself reached a terminal state. Cancellation shows Stopped. The card and below-prompt count update in the owning main or workflow-stage chat.
|
|
220
284
|
|
package/docs/settings.md
CHANGED
|
@@ -499,6 +499,16 @@ Plain names establish a replacement list before its modifiers apply. A project l
|
|
|
499
499
|
|
|
500
500
|
`codemode` and `tool_search` are built-in extension tools registered inactive. Add `"+codemode"` or `"+tool_search"` to `defaultTools` to activate them alongside ordinary defaults. See [codemode](/tools#codemode) and [tool search](/tools#tool_search) for usage and safety boundaries.
|
|
501
501
|
|
|
502
|
+
### Tasks
|
|
503
|
+
|
|
504
|
+
| Setting | Type | Default | Description |
|
|
505
|
+
|---------|------|---------|-------------|
|
|
506
|
+
| `tasks.heartbeatMs` | number | `900000` | How often, in milliseconds, a running background shell or subagent sends its chat a [task heartbeat](/background-tasks#task-heartbeats). `0` turns heartbeats off; other values must be at least `60000`. An invalid value uses the default. A tool call's `heartbeatMs` overrides it for that task. |
|
|
507
|
+
|
|
508
|
+
```json
|
|
509
|
+
{ "tasks": { "heartbeatMs": 1800000 } }
|
|
510
|
+
```
|
|
511
|
+
|
|
502
512
|
### Sessions
|
|
503
513
|
|
|
504
514
|
| Setting | Type | Default | Description |
|
|
@@ -607,6 +617,8 @@ Local worker pools are disabled unless `workflows.localWorkers` is set. With the
|
|
|
607
617
|
|
|
608
618
|
`leaseMs` is how long, in milliseconds, a worker that is still running but has stopped responding keeps its child before the child is replayed on another worker. It defaults to `30000` and must be at least `2000`. A worker that exits is replaced immediately, and a worker that is still responding keeps its child even when the pool is briefly too busy to process its heartbeats. Like `startupTimeoutMs`, this value is not saved with the root.
|
|
609
619
|
|
|
620
|
+
`maxLoadPerCpu` keeps an overloaded machine from being given a burst of stages to start. While the 1-minute load average divided by the number of CPU cores is above it, the stages of pooled children start one at a time, at most one every 5 seconds, in the order they asked, instead of all at once while earlier ones are still starting. Running stages, the subagents they start and their tool processes are not held. It defaults to `3`; `0` turns it off. It is not saved with the root, so you can change it before resuming. `admission.host.maxLoadPerCpu` below is a separate gate on every session and process launch.
|
|
621
|
+
|
|
610
622
|
`limits` caps agent sessions and managed tool processes for one root. Session permits cover creation through disposal, including fallback and delegated sessions. Process permits last until confirmed cleanup; yielding an observation wait does not free one. Processes outside Atomic's managed tools are not counted. `host` load and memory thresholds gate launches but do not impose hard OS limits.
|
|
611
623
|
|
|
612
624
|
`userLimits` counts across runs only when all participating runs use the same canonical local SQLite journal. Set `userDatabase` to that exact path, and pass the admission options to participating non-pooled SDK runs. When the pool's journal is a remote database or another journal that is not a default local SQLite file, omit `userDatabase`: the limit then counts across the pooled roots on this machine that use that journal. This coordinates processes for one local user; it is not a tenant isolation boundary.
|
package/docs/subagents.md
CHANGED
|
@@ -74,6 +74,8 @@ Runtime-created session contexts bind single launches to their actual session or
|
|
|
74
74
|
- `wait: {kind: "background"}` uses reason `explicit`.
|
|
75
75
|
- `wait: {kind: "foreground", budgetMs: 30000}` opts into foreground-first observation. The omitted foreground budget is 30000 ms.
|
|
76
76
|
|
|
77
|
+
A running child sends the parent a [task heartbeat](/background-tasks#task-heartbeats) every 15 minutes by default, with its current tool call, time since its last activity, and turn, tool-call and token counts. Set `heartbeatMs` on the call, or on a `tasks` entry, to change that child's cadence; `0` turns it off.
|
|
78
|
+
|
|
77
79
|
When you issue several single-agent calls in one turn, each keeps its own `wait` policy and returns only its own task result. Background completions appear as visible notices and notify the parent agent, including in workflow-stage chats receiving other messages.
|
|
78
80
|
|
|
79
81
|
These calls share the `concurrency` limit, or the configured subagent parallel limit when omitted, even when their wait policies differ. A background receipt or an expired foreground observation does not free a running child's slot; queued children start when execution capacity becomes available.
|
package/docs/tools.md
CHANGED
|
@@ -441,11 +441,12 @@ Custom `WriteOperations` implementations must read from the same filesystem they
|
|
|
441
441
|
|
|
442
442
|
## `bash` and `bashInterceptor`
|
|
443
443
|
|
|
444
|
-
The `bash` tool executes shell commands in the session workspace. It accepts `cwd`, `env`, `timeout`, and `
|
|
444
|
+
The `bash` tool executes shell commands in the session workspace. It accepts `cwd`, `env`, `timeout`, `pty`, and `heartbeatMs`.
|
|
445
445
|
|
|
446
446
|
- `cwd` and `env` set the working directory and environment for local execution.
|
|
447
447
|
- `timeout` is in seconds and defaults to 300. Explicit values must be finite, greater than zero, and no more than 3600. Invalid values fail before execution. Fractions round down, with a one-second floor.
|
|
448
448
|
- `pty: true` uses the bundled native PTY session, falling back to pipes if unavailable. Set `PI_NO_PTY=1` or `ATOMIC_NO_PTY=1` to force pipes.
|
|
449
|
+
- `heartbeatMs` sets how often a command that keeps running as a background task sends a [task heartbeat](/background-tasks#task-heartbeats). Omit it for the chat's default (15 minutes unless `tasks.heartbeatMs` changes it), use `0` to turn heartbeats off, or give at least `60000`.
|
|
449
450
|
|
|
450
451
|
Foreground results include `timeoutSeconds`, `requestedTimeoutSeconds`, `wallTimeMs`, and non-zero `exitCode` metadata. Truncated output is saved at `fullOutputPath`.
|
|
451
452
|
|
|
@@ -882,11 +882,11 @@ Pools work with any journal the worker processes can open by the same selection:
|
|
|
882
882
|
|
|
883
883
|
The supported placement is multiple local processes on Linux or macOS. Windows and any host without native process identity and boot identity refuse activation with an error. This is a containment requirement: lease expiry does not prove that an old process stopped. Remote hosts and network workers are not supported.
|
|
884
884
|
|
|
885
|
-
The root's existing `/workflow status`, `/workflow stages`, steering, pause, quit, and resume controls still address one root. A worker failure can replay an unfinished child from its last committed checkpoint. This is at-least-once recovery. An external effect that happens before its checkpoint can happen again; use stable logical idempotency keys for effects that must not duplicate.
|
|
885
|
+
The root's existing `/workflow status`, `/workflow stages`, steering, pause, quit, and resume controls still address one root. A run paused this way can be resumed with `/workflow resume <run>` from a new Atomic process, for example after an upgrade, once the process that paused it has exited; children that an earlier process failed because of a fault of the pool itself run again. `/workflow pause <run>` pauses the stages on local workers even while the root's own steps run; on a busy machine some workers can take a few seconds to confirm, and the pause reports how many stages have not confirmed yet. They pause on their own, so pausing again is not needed. A worker failure can replay an unfinished child from its last committed checkpoint. This is at-least-once recovery. An external effect that happens before its checkpoint can happen again; use stable logical idempotency keys for effects that must not duplicate.
|
|
886
886
|
|
|
887
887
|
### Watching stages on local workers
|
|
888
888
|
|
|
889
|
-
A stage that runs on a local worker opens from the workflow graph or `/workflow attach` like any other stage. While it runs, its chat shows the transcript so far and the reply as it streams, with tool calls. The chat header reads `on local worker`. Enter steers the running turn and Ctrl+F queues a follow-up, as for any stage. Queued messages show on the stage's graph node (`✉ N queued`) even when its chat is closed. `/workflow pause <run> <stage>` and the stage chat's pause and resume hold and release just that stage; other stages, including ones on other workers, keep running, and the paused stage keeps its worker. While the whole pool is paused, a single stage cannot be paused or resumed on its own; resume the run first.
|
|
889
|
+
A stage that runs on a local worker opens from the workflow graph or `/workflow attach` like any other stage. While its session is still starting on the worker (loading resources, creating the session), the stage reads as `queued` with what it is doing, such as `creating session 32s`, on its graph node, in the stage list, `/workflow status` and the `workflow` tool's stage list, and its chat says it is starting on its local worker. The chat streams the stage as soon as its session starts; messages you send meanwhile are delivered then. While it runs, its chat shows the transcript so far and the reply as it streams, with tool calls. The chat header reads `on local worker`. Enter steers the running turn and Ctrl+F queues a follow-up, as for any stage. `/skill:` commands complete with the stage's own skills, `/compact` compacts the stage's session, and a `!` command runs in the stage's working directory on its worker. `/tasks` and the task footer list the stage's agents and shells on its worker; you can view their output and transcripts, send input and stop them there. Queued messages show on the stage's graph node (`✉ N queued`) even when its chat is closed. `/workflow pause <run> <stage>` and the stage chat's pause and resume hold and release just that stage; other stages, including ones on other workers, keep running, and the paused stage keeps its worker. While the whole pool is paused, a single stage cannot be paused or resumed on its own; resume the run first.
|
|
890
890
|
|
|
891
891
|
If the worker running an open stage dies or loses its lease, the chat header shows `RECONNECTING` until the stage runs again on a replacement worker. The chat then reloads from the replacement's transcript and sends again, once each, in the order and the mode you sent them (a steer still steers the running turn, a follow-up still waits for it), the messages the replacement does not have, such as messages that were still queued. The header then shows how many were redelivered. Messages you sent stay queued for the stage even if you close its chat before they arrive, and they are delivered when the stage runs again. If the stage or its run ends first, the header shows how many messages were not delivered.
|
|
892
892
|
|
|
@@ -902,7 +902,7 @@ Each worker process must report that it is ready within `localWorkers.startupTim
|
|
|
902
902
|
|
|
903
903
|
A worker that exits is detected immediately, and its child is replayed from its last committed checkpoint on a replacement worker. A worker that is still running keeps its child as long as it keeps responding, even when the pool is briefly too busy to process its heartbeats. Only a running worker that has not responded for `localWorkers.leaseMs` milliseconds (30000 by default) is stopped and its child replayed. When a root is resumed after its process crashed, children that were held by the crashed process's workers are replayed on the new workers right away.
|
|
904
904
|
|
|
905
|
-
A worker that exits or is killed while it runs a child does not stop the root. The root fences that worker's attempt and replays the child from its last committed checkpoint on a replacement worker, up to three attempts per child. A child that loses its third worker fails alone with `worker_retry_limit`; the pool and the root's other children keep running.
|
|
905
|
+
A worker that exits or is killed while it runs a child does not stop the root. The root fences that worker's attempt and replays the child from its last committed checkpoint on a replacement worker, up to three attempts per child. A child that loses its third worker fails alone with `worker_retry_limit`; the pool and the root's other children keep running. A fault of the pool itself that reaches a running child, such as a journal write the database refused, replays the child the same way instead of failing its stage. A busy machine slows workers but does not fail them: a worker that still responds keeps its child however late its heartbeats are processed, and a stage's queued Intercom messages are delivered however slowly the worker acknowledges them. A stage that does fail on a pool fault records it as its failure code (for example `worker_lost` or `stale_work_lease`) and as recoverable, and `/workflow resume` runs it again.
|
|
906
906
|
|
|
907
907
|
If the root process exits, even when it is killed, the pool's coordinator and workers exit with it. Resume the root to continue its children. If the coordinator process itself dies, its workers exit with it, and each pooled child the root is waiting on fails with the retryable `worker_lost` fault and the message `Local worker pool coordinator exited (…)`.
|
|
908
908
|
|
|
@@ -914,6 +914,8 @@ Each worker writes its standard error to `worker-logs/<root run ID>/<worker ID>.
|
|
|
914
914
|
|
|
915
915
|
`admission.host` adds launch gates for load per CPU and free memory. These measurements are advisory; they are not operating-system resource ceilings.
|
|
916
916
|
|
|
917
|
+
Without any `admission` setting, pooled stages still start one at a time, at most one every 5 seconds, while the machine's load per CPU is above `localWorkers.maxLoadPerCpu` (default `3`). See [Local worker pools](/settings#local-worker-pools).
|
|
918
|
+
|
|
917
919
|
`admission.userLimits` applies the selected session or process limit across runs that use a single canonical local SQLite journal path. Set `userDatabase` to that same path. For pooled roots on a journal in another database, the limit counts across the pooled roots on this machine that use that journal; omit `userDatabase`. A conflicting journal selection or unsupported storage fails clearly instead of claiming a cross-run limit that cannot be enforced. This is local-user coordination, not a multi-tenant security boundary. Include the admission option on participating non-pooled SDK runs if they should share the user-wide limit.
|
|
918
920
|
|
|
919
921
|
Pooled SDK runs reject process-bound adapter, UI, persistence and similar runtime overrides before launch. CLI-owned host bindings remain local to the root; workers construct their own stage sessions.
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.58-alpha.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bastani/atomic",
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.58-alpha.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bastani/atomic-natives": "0.9.
|
|
13
|
-
"@bastani/pi-ai": "0.9.
|
|
12
|
+
"@bastani/atomic-natives": "0.9.58-alpha.1",
|
|
13
|
+
"@bastani/pi-ai": "0.9.58-alpha.1",
|
|
14
14
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
15
15
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
16
16
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -427,18 +427,18 @@
|
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
429
|
"node_modules/@bastani/atomic-natives": {
|
|
430
|
-
"version": "0.9.
|
|
431
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.
|
|
430
|
+
"version": "0.9.58-alpha.1",
|
|
431
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.58-alpha.1.tgz",
|
|
432
432
|
"license": "MIT",
|
|
433
433
|
"optionalDependencies": {
|
|
434
|
-
"@bastani/atomic-natives-darwin-arm64": "0.9.
|
|
435
|
-
"@bastani/atomic-natives-darwin-x64": "0.9.
|
|
436
|
-
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.
|
|
437
|
-
"@bastani/atomic-natives-linux-arm64-musl": "0.9.
|
|
438
|
-
"@bastani/atomic-natives-linux-x64-gnu": "0.9.
|
|
439
|
-
"@bastani/atomic-natives-linux-x64-musl": "0.9.
|
|
440
|
-
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.
|
|
441
|
-
"@bastani/atomic-natives-win32-x64-msvc": "0.9.
|
|
434
|
+
"@bastani/atomic-natives-darwin-arm64": "0.9.58-alpha.1",
|
|
435
|
+
"@bastani/atomic-natives-darwin-x64": "0.9.58-alpha.1",
|
|
436
|
+
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.58-alpha.1",
|
|
437
|
+
"@bastani/atomic-natives-linux-arm64-musl": "0.9.58-alpha.1",
|
|
438
|
+
"@bastani/atomic-natives-linux-x64-gnu": "0.9.58-alpha.1",
|
|
439
|
+
"@bastani/atomic-natives-linux-x64-musl": "0.9.58-alpha.1",
|
|
440
|
+
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.58-alpha.1",
|
|
441
|
+
"@bastani/atomic-natives-win32-x64-msvc": "0.9.58-alpha.1"
|
|
442
442
|
},
|
|
443
443
|
"engines": {
|
|
444
444
|
"bun": ">=1.4.2",
|
|
@@ -446,8 +446,8 @@
|
|
|
446
446
|
}
|
|
447
447
|
},
|
|
448
448
|
"node_modules/@bastani/atomic-natives-darwin-arm64": {
|
|
449
|
-
"version": "0.9.
|
|
450
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.
|
|
449
|
+
"version": "0.9.58-alpha.1",
|
|
450
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.58-alpha.1.tgz",
|
|
451
451
|
"license": "MIT",
|
|
452
452
|
"os": [
|
|
453
453
|
"darwin"
|
|
@@ -458,8 +458,8 @@
|
|
|
458
458
|
"optional": true
|
|
459
459
|
},
|
|
460
460
|
"node_modules/@bastani/atomic-natives-darwin-x64": {
|
|
461
|
-
"version": "0.9.
|
|
462
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.
|
|
461
|
+
"version": "0.9.58-alpha.1",
|
|
462
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.58-alpha.1.tgz",
|
|
463
463
|
"license": "MIT",
|
|
464
464
|
"os": [
|
|
465
465
|
"darwin"
|
|
@@ -470,8 +470,8 @@
|
|
|
470
470
|
"optional": true
|
|
471
471
|
},
|
|
472
472
|
"node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
|
|
473
|
-
"version": "0.9.
|
|
474
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.
|
|
473
|
+
"version": "0.9.58-alpha.1",
|
|
474
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.58-alpha.1.tgz",
|
|
475
475
|
"license": "MIT",
|
|
476
476
|
"os": [
|
|
477
477
|
"linux"
|
|
@@ -485,8 +485,8 @@
|
|
|
485
485
|
"optional": true
|
|
486
486
|
},
|
|
487
487
|
"node_modules/@bastani/atomic-natives-linux-arm64-musl": {
|
|
488
|
-
"version": "0.9.
|
|
489
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.
|
|
488
|
+
"version": "0.9.58-alpha.1",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.58-alpha.1.tgz",
|
|
490
490
|
"license": "MIT",
|
|
491
491
|
"os": [
|
|
492
492
|
"linux"
|
|
@@ -500,8 +500,8 @@
|
|
|
500
500
|
"optional": true
|
|
501
501
|
},
|
|
502
502
|
"node_modules/@bastani/atomic-natives-linux-x64-gnu": {
|
|
503
|
-
"version": "0.9.
|
|
504
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.
|
|
503
|
+
"version": "0.9.58-alpha.1",
|
|
504
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.58-alpha.1.tgz",
|
|
505
505
|
"license": "MIT",
|
|
506
506
|
"os": [
|
|
507
507
|
"linux"
|
|
@@ -515,8 +515,8 @@
|
|
|
515
515
|
"optional": true
|
|
516
516
|
},
|
|
517
517
|
"node_modules/@bastani/atomic-natives-linux-x64-musl": {
|
|
518
|
-
"version": "0.9.
|
|
519
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.
|
|
518
|
+
"version": "0.9.58-alpha.1",
|
|
519
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.58-alpha.1.tgz",
|
|
520
520
|
"license": "MIT",
|
|
521
521
|
"os": [
|
|
522
522
|
"linux"
|
|
@@ -530,8 +530,8 @@
|
|
|
530
530
|
"optional": true
|
|
531
531
|
},
|
|
532
532
|
"node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
|
|
533
|
-
"version": "0.9.
|
|
534
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.
|
|
533
|
+
"version": "0.9.58-alpha.1",
|
|
534
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.58-alpha.1.tgz",
|
|
535
535
|
"license": "MIT",
|
|
536
536
|
"os": [
|
|
537
537
|
"win32"
|
|
@@ -542,8 +542,8 @@
|
|
|
542
542
|
"optional": true
|
|
543
543
|
},
|
|
544
544
|
"node_modules/@bastani/atomic-natives-win32-x64-msvc": {
|
|
545
|
-
"version": "0.9.
|
|
546
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.
|
|
545
|
+
"version": "0.9.58-alpha.1",
|
|
546
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.58-alpha.1.tgz",
|
|
547
547
|
"license": "MIT",
|
|
548
548
|
"os": [
|
|
549
549
|
"win32"
|
|
@@ -554,8 +554,8 @@
|
|
|
554
554
|
"optional": true
|
|
555
555
|
},
|
|
556
556
|
"node_modules/@bastani/pi-ai": {
|
|
557
|
-
"version": "0.9.
|
|
558
|
-
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.
|
|
557
|
+
"version": "0.9.58-alpha.1",
|
|
558
|
+
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.58-alpha.1.tgz",
|
|
559
559
|
"license": "MIT",
|
|
560
560
|
"dependencies": {
|
|
561
561
|
"@anthropic-ai/sdk": "0.129.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.58-alpha.1",
|
|
4
4
|
"description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"atomicConfig": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@bastani/atomic-natives": "0.9.
|
|
93
|
-
"@bastani/pi-ai": "0.9.
|
|
92
|
+
"@bastani/atomic-natives": "0.9.58-alpha.1",
|
|
93
|
+
"@bastani/pi-ai": "0.9.58-alpha.1",
|
|
94
94
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
95
95
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
96
96
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -579,6 +579,11 @@
|
|
|
579
579
|
"minimum": 2000,
|
|
580
580
|
"maximum": 2147483647,
|
|
581
581
|
"description": "Milliseconds a live worker that has stopped responding keeps its child before the child is replayed elsewhere. Default: 30000."
|
|
582
|
+
},
|
|
583
|
+
"maxLoadPerCpu": {
|
|
584
|
+
"type": "number",
|
|
585
|
+
"minimum": 0,
|
|
586
|
+
"description": "Load per CPU (1-minute load average / CPU cores) above which pooled stages start one at a time, at most one every 5 seconds. Default: 3. 0 turns it off."
|
|
582
587
|
}
|
|
583
588
|
},
|
|
584
589
|
"additionalProperties": false
|
|
@@ -958,6 +963,25 @@
|
|
|
958
963
|
}
|
|
959
964
|
}
|
|
960
965
|
},
|
|
966
|
+
"tasks": {
|
|
967
|
+
"type": "object",
|
|
968
|
+
"properties": {
|
|
969
|
+
"heartbeatMs": {
|
|
970
|
+
"anyOf": [
|
|
971
|
+
{
|
|
972
|
+
"type": "number",
|
|
973
|
+
"const": 0
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
"type": "number",
|
|
977
|
+
"minimum": 60000
|
|
978
|
+
}
|
|
979
|
+
],
|
|
980
|
+
"description": "Default cadence, in milliseconds, of the periodic heartbeat sent to a chat for each of its running background shells and subagents. 0 disables; otherwise at least 60000. A tool call's heartbeatMs overrides it.",
|
|
981
|
+
"default": 900000
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
},
|
|
961
985
|
"httpProxy": {
|
|
962
986
|
"type": "string",
|
|
963
987
|
"description": "Proxy URL applied as HTTP_PROXY and HTTPS_PROXY for Atomic-managed HTTP clients. Global only."
|