@fastagent-sh/fastagent 0.17.1 → 0.19.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 +25 -7
- package/dist/agent.d.ts +12 -1
- package/dist/agent.js +1 -1
- package/dist/atomic-write.d.ts +19 -0
- package/dist/atomic-write.js +48 -0
- package/dist/{host/node.d.ts → channel.d.ts} +24 -28
- package/dist/channel.js +1 -0
- package/dist/channels/agentcore-service.d.ts +54 -0
- package/dist/channels/agentcore-service.js +111 -0
- package/dist/channels/agentcore.d.ts +12 -2
- package/dist/channels/agentcore.js +6 -4
- package/dist/channels/busy.d.ts +1 -1
- package/dist/channels/busy.js +1 -1
- package/dist/channels/control.d.ts +16 -6
- package/dist/channels/control.js +106 -4
- package/dist/{engines/pi/channel.d.ts → channels/discover.d.ts} +2 -2
- package/dist/{engines/pi/channel.js → channels/discover.js} +8 -12
- package/dist/channels/feishu/card.js +1 -1
- package/dist/channels/feishu/context-buffer.d.ts +1 -1
- package/dist/channels/feishu/context-buffer.js +4 -4
- package/dist/channels/feishu/feishu-api.d.ts +4 -2
- package/dist/channels/feishu/feishu-api.js +1 -1
- package/dist/channels/feishu/feishu.d.ts +1 -1
- package/dist/channels/feishu/feishu.js +45 -15
- package/dist/channels/feishu/invoke-turn.d.ts +9 -3
- package/dist/channels/feishu/invoke-turn.js +152 -34
- package/dist/channels/feishu/parse.js +6 -0
- package/dist/channels/feishu/preview.d.ts +1 -1
- package/dist/channels/feishu/preview.js +7 -3
- package/dist/channels/feishu/ws-ingress.d.ts +1 -1
- package/dist/channels/github/github.d.ts +1 -1
- package/dist/channels/http.d.ts +11 -7
- package/dist/channels/http.js +16 -111
- package/dist/channels/{context-buffer.js → kit/context-buffer.js} +2 -2
- package/dist/channels/{invoke-turn-kit.d.ts → kit/invoke-turn-kit.d.ts} +18 -4
- package/dist/channels/{invoke-turn-kit.js → kit/invoke-turn-kit.js} +23 -8
- package/dist/channels/{preview-kit.d.ts → kit/preview-kit.d.ts} +3 -1
- package/dist/channels/{seen.js → kit/seen.js} +1 -1
- package/dist/channels/kit/state.d.ts +6 -0
- package/dist/channels/{state.js → kit/state.js} +4 -24
- package/dist/channels/{stop-command.d.ts → kit/stop-command.d.ts} +1 -1
- package/dist/channels/{stop-command.js → kit/stop-command.js} +2 -2
- package/dist/channels/{tasks.js → kit/tasks.js} +1 -1
- package/dist/channels/{thread-participants.d.ts → kit/thread-participants.d.ts} +7 -0
- package/dist/channels/{thread-participants.js → kit/thread-participants.js} +4 -1
- package/dist/channels/{turn-queue.js → kit/turn-queue.js} +2 -2
- package/dist/channels/{turn-store.js → kit/turn-store.js} +1 -1
- package/dist/channels/lark/lark.d.ts +1 -1
- package/dist/channels/serve.d.ts +73 -0
- package/dist/channels/serve.js +243 -0
- package/dist/channels/slack/bot-auth.js +3 -14
- package/dist/channels/slack/context-buffer.d.ts +2 -2
- package/dist/channels/slack/context-buffer.js +2 -2
- package/dist/channels/slack/invoke-turn.d.ts +1 -1
- package/dist/channels/slack/invoke-turn.js +9 -6
- package/dist/channels/slack/parse.js +2 -2
- package/dist/channels/slack/preview.d.ts +1 -1
- package/dist/channels/slack/preview.js +11 -3
- package/dist/channels/slack/slack-api.js +1 -1
- package/dist/channels/slack/slack.d.ts +1 -1
- package/dist/channels/slack/slack.js +8 -12
- package/dist/channels/slack/welcomed.js +1 -1
- package/dist/channels/telegram/context-buffer.d.ts +2 -2
- package/dist/channels/telegram/context-buffer.js +2 -2
- package/dist/channels/telegram/invoke-turn.d.ts +1 -1
- package/dist/channels/telegram/invoke-turn.js +2 -2
- package/dist/channels/telegram/parse.js +2 -2
- package/dist/channels/telegram/preview.d.ts +1 -1
- package/dist/channels/telegram/preview.js +6 -2
- package/dist/channels/telegram/telegram.d.ts +1 -1
- package/dist/channels/telegram/telegram.js +3 -3
- package/dist/channels/telegram/turn-store.d.ts +2 -2
- package/dist/channels/telegram/turn-store.js +2 -2
- package/dist/cli/commands/add.js +1 -1
- package/dist/cli/commands/deploy.js +13 -5
- package/dist/cli/commands/dev.js +26 -14
- package/dist/cli/commands/fire.js +2 -2
- package/dist/cli/commands/info.js +28 -5
- package/dist/cli/commands/invoke.js +1 -1
- package/dist/cli/commands/schedule.js +1 -1
- package/dist/cli/commands/start.js +64 -95
- package/dist/cli/commands/tool.js +5 -7
- package/dist/cli/program.js +1 -1
- package/dist/cli/serve.d.ts +18 -57
- package/dist/cli/serve.js +57 -243
- package/dist/cli/shared.d.ts +5 -3
- package/dist/cli/shared.js +14 -7
- package/dist/collect.d.ts +30 -4
- package/dist/collect.js +39 -6
- package/dist/core.d.ts +3 -5
- package/dist/core.js +7 -5
- package/dist/deploy/preflight.d.ts +8 -2
- package/dist/deploy/preflight.js +22 -4
- package/dist/deploy/secrets.d.ts +3 -0
- package/dist/deploy/secrets.js +6 -0
- package/dist/dev-supervisor.js +16 -4
- package/dist/engines/pi/agent-session-factory.d.ts +104 -0
- package/dist/engines/pi/agent-session-factory.js +314 -0
- package/dist/engines/pi/config.d.ts +4 -4
- package/dist/engines/pi/config.js +1 -1
- package/dist/engines/pi/create.d.ts +56 -42
- package/dist/engines/pi/create.js +150 -75
- package/dist/engines/pi/definition.d.ts +41 -7
- package/dist/engines/pi/definition.js +115 -11
- package/dist/engines/pi/invoke-session.d.ts +35 -0
- package/dist/engines/pi/invoke-session.js +357 -0
- package/dist/engines/pi/login.js +7 -4
- package/dist/engines/pi/models.d.ts +59 -11
- package/dist/engines/pi/models.js +64 -9
- package/dist/engines/pi/open.d.ts +9 -6
- package/dist/engines/pi/open.js +20 -10
- package/dist/engines/pi/report.d.ts +0 -4
- package/dist/engines/pi/report.js +0 -7
- package/dist/engines/pi/service.d.ts +23 -0
- package/dist/engines/pi/service.js +19 -0
- package/dist/engines/pi/session-builder.js +88 -90
- package/dist/engines/pi/session-control.d.ts +11 -9
- package/dist/engines/pi/session-control.js +114 -77
- package/dist/engines/pi/session-inheritance.d.ts +44 -0
- package/dist/engines/pi/session-inheritance.js +242 -0
- package/dist/engines/pi/session-settings.d.ts +14 -2
- package/dist/engines/pi/session-settings.js +18 -0
- package/dist/engines/pi/session-store.d.ts +70 -0
- package/dist/engines/pi/session-store.js +313 -0
- package/dist/engines/pi/tool-context.d.ts +18 -8
- package/dist/engines/pi/tool-context.js +23 -1
- package/dist/engines/pi/tool.d.ts +5 -5
- package/dist/engines/pi/tool.js +1 -1
- package/dist/engines/pi/{invoke.d.ts → turn-kit.d.ts} +46 -45
- package/dist/engines/pi/turn-kit.js +188 -0
- package/dist/engines/pi/wake-tool.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/log.d.ts +3 -0
- package/dist/log.js +5 -1
- package/dist/node.d.ts +16 -0
- package/dist/node.js +20 -0
- package/dist/paths.d.ts +13 -0
- package/dist/paths.js +16 -0
- package/dist/pi.d.ts +15 -8
- package/dist/pi.js +7 -6
- package/dist/scaffold/templates/fastagent.config.mjs +2 -0
- package/dist/scaffold/templates/persona.md +2 -2
- package/dist/schedule/state.js +4 -9
- package/dist/schedule/wakeups.d.ts +1 -1
- package/dist/schedule/wakeups.js +1 -1
- package/dist/service.d.ts +158 -0
- package/dist/service.js +354 -0
- package/dist/session-remote.d.ts +1 -1
- package/dist/session-remote.js +10 -2
- package/dist/session.d.ts +4 -2
- package/dist/session.js +1 -1
- package/package.json +14 -5
- package/dist/channels/state.d.ts +0 -16
- package/dist/engines/pi/harness.d.ts +0 -112
- package/dist/engines/pi/harness.js +0 -153
- package/dist/engines/pi/invoke.js +0 -618
- package/dist/engines/pi/read-image.d.ts +0 -4
- package/dist/engines/pi/read-image.js +0 -62
- package/dist/engines/pi/sessions.d.ts +0 -44
- package/dist/engines/pi/sessions.js +0 -182
- package/dist/host/node.js +0 -52
- /package/dist/channels/{context-buffer.d.ts → kit/context-buffer.d.ts} +0 -0
- /package/dist/channels/{preview-kit.js → kit/preview-kit.js} +0 -0
- /package/dist/channels/{seen.d.ts → kit/seen.d.ts} +0 -0
- /package/dist/channels/{tasks.d.ts → kit/tasks.d.ts} +0 -0
- /package/dist/channels/{text.d.ts → kit/text.d.ts} +0 -0
- /package/dist/channels/{text.js → kit/text.js} +0 -0
- /package/dist/channels/{turn-queue.d.ts → kit/turn-queue.d.ts} +0 -0
- /package/dist/channels/{turn-store.d.ts → kit/turn-store.d.ts} +0 -0
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pi harness wiring: construct one pi `AgentHarness` per session. The agent definition (AGENTS.md +
|
|
3
|
-
* skills) is content fed INTO the harness (see definition.ts), not part of it.
|
|
4
|
-
*
|
|
5
|
-
* Under the stateless design the harness is discarded after each use; continuity comes from
|
|
6
|
-
* persisting the session (PiSessionStore) and re-opening it per invoke — pi's prompt() folds the
|
|
7
|
-
* historical entries back into context via buildContext().
|
|
8
|
-
*/
|
|
9
|
-
import { AgentHarness } from "@earendil-works/pi-agent-core";
|
|
10
|
-
import { log } from "../../log.js";
|
|
11
|
-
import { activePathEntries } from "./sessions.js";
|
|
12
|
-
import { isDeferredTool } from "./tool.js";
|
|
13
|
-
import { resolveSessionSettings } from "./session-settings.js";
|
|
14
|
-
/**
|
|
15
|
-
* The session custom-entry type recording ONE activation delta: `{ names }` — exactly the deferred
|
|
16
|
-
* tools a loader activated in that call. The DEDICATED record the resolve below reads: pi's own
|
|
17
|
-
* `active_tools_change` entries are full active-set SNAPSHOTS (setActiveTools persists everything
|
|
18
|
-
* active at that moment), and reinterpreting a snapshot as activations would keep a tool active in
|
|
19
|
-
* old sessions after the author flips it to `deferred` — the session never discovered it. Deltas
|
|
20
|
-
* carry only what was actually discovered.
|
|
21
|
-
*/
|
|
22
|
-
export const TOOL_ACTIVATION_ENTRY = "fastagent:tool-activation";
|
|
23
|
-
const harnessSessions = new WeakMap();
|
|
24
|
-
export function harnessSession(harness) {
|
|
25
|
-
return harnessSessions.get(harness);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Provider request retries. The OpenAI-family / Anthropic / Azure / Codex pi-ai adapters
|
|
29
|
-
* implement client-side retries (429/5xx/request-phase network failures with backoff, honoring
|
|
30
|
-
* Retry-After; a Codex websocket that fails before the stream starts falls back to SSE) but all
|
|
31
|
-
* default maxRetries to 0 (even SDK-backed ones override the SDK default), so a single transient
|
|
32
|
-
* `fetch failed` would otherwise kill the whole turn; 2 matches the OpenAI/Anthropic SDK default.
|
|
33
|
-
* The google / vertex / bedrock / mistral adapters ignore this option (a pi-ai upstream gap) —
|
|
34
|
-
* transients there still fail the turn. Mid-stream drops are deliberately NOT retried anywhere on
|
|
35
|
-
* this path — partial output was already streamed and the SPEC event stream cannot retract it,
|
|
36
|
-
* so a mid-stream failure surfaces as a `failed` event.
|
|
37
|
-
*/
|
|
38
|
-
const PROVIDER_MAX_RETRIES = 2;
|
|
39
|
-
/**
|
|
40
|
-
* Retry policy for generated compaction/branch-summary model calls (pi ≥0.81.1, #6901). OPT-IN
|
|
41
|
-
* upstream — an undefined policy means no retries — so both compaction paths pass it explicitly:
|
|
42
|
-
* the harness config (auto-compaction inside a run) and the manual `compact()` dispatch in
|
|
43
|
-
* session-control. Values mirror pi's own app defaults (maxRetries 3, base 2s exponential).
|
|
44
|
-
*/
|
|
45
|
-
export const SUMMARIZATION_RETRY_POLICY = { enabled: true, maxRetries: 3, baseDelayMs: 2000 };
|
|
46
|
-
/**
|
|
47
|
-
* The serving default for reasoning effort, pinned to what pi's TUI defaults to (its
|
|
48
|
-
* DEFAULT_THINKING_LEVEL) — NOT inherited from the bare harness, whose own fallback is "off": an
|
|
49
|
-
* author vibes at "medium" in pi and must get "medium" when served (fidelity), and pinning the value
|
|
50
|
-
* here means an upstream default change in either place cannot silently alter deployments. Models
|
|
51
|
-
* that don't support a level are clamped by pi per model.
|
|
52
|
-
*/
|
|
53
|
-
export const DEFAULT_THINKING_LEVEL = "medium";
|
|
54
|
-
/**
|
|
55
|
-
* Resolve the active-tool set for a fresh harness — the ONE place both fallbacks live. pi's harness
|
|
56
|
-
* WRITES active-tool changes to the session (`setActiveTools` → `active_tools_change`) but its
|
|
57
|
-
* constructor never reads them back — pi's long-lived TUI harness keeps the set in memory, while
|
|
58
|
-
* fastagent builds a FRESH harness per invoke, which would silently reset the session's active set
|
|
59
|
-
* every turn.
|
|
60
|
-
*
|
|
61
|
-
* No record (`null`) → the INITIAL set: every non-deferred tool; undefined when nothing is deferred
|
|
62
|
-
* (pi's default — all active — applies, and no session entry is ever written; tool-sets without
|
|
63
|
-
* deferral behave exactly as before deferral existed).
|
|
64
|
-
*
|
|
65
|
-
* A record is NOT replayed as a frozen snapshot — the active set is rebuilt as the UNION of the
|
|
66
|
-
* initial set and the recorded names (filtered to the mounted tools: the constructor THROWS on
|
|
67
|
-
* unknown names, so a recorded-but-removed tool would otherwise brick every future invoke of that
|
|
68
|
-
* session). On the serving path only the additive activation bridge writes records, so a record's
|
|
69
|
-
* real semantic is "which deferred tools this session activated" — layered on top of whatever the
|
|
70
|
-
* workspace mounts TODAY. A snapshot replay would silently freeze a later-added non-deferred tool
|
|
71
|
-
* out of every session the loader ever touched. Missing recorded names are logged (fail visibly) —
|
|
72
|
-
* ONCE per session+missing set: a fresh harness is built per invoke and channel sessions live for
|
|
73
|
-
* weeks, so an un-deduped warn would repeat every turn and dilute its own signal. A log-dedup memo
|
|
74
|
-
* (like L2's findings memo), not session state — the resolve stays derived from the session.
|
|
75
|
-
*/
|
|
76
|
-
const warnedRestores = new Set();
|
|
77
|
-
/**
|
|
78
|
-
* {@link resolveSessionSettings} plus the warn only the execution path owes: a recorded pair can stop
|
|
79
|
-
* being executable with no control-plane command involved (pi appends these entries itself; a
|
|
80
|
-
* deployment's configured model can change between restarts). Deduped per session+cause — it would
|
|
81
|
-
* otherwise repeat every turn.
|
|
82
|
-
*/
|
|
83
|
-
export function resolveHarnessOverrides(entries, models, defaults, sessionId) {
|
|
84
|
-
const settings = resolveSessionSettings(entries, models, defaults);
|
|
85
|
-
const warnOnce = (key, message) => {
|
|
86
|
-
const emit = warnedRestores.has(key) ? log.debug : log.warn;
|
|
87
|
-
warnedRestores.add(key);
|
|
88
|
-
emit(message);
|
|
89
|
-
};
|
|
90
|
-
const dropped = settings.dropped;
|
|
91
|
-
if (dropped?.model) {
|
|
92
|
-
warnOnce(`${sessionId}\u0000model\u0000${dropped.model}`, `[fastagent] session ${sessionId}: recorded model override ${dropped.model} is not in this deployment's registry — using the configured default`);
|
|
93
|
-
}
|
|
94
|
-
if (dropped?.thinkingLevel) {
|
|
95
|
-
const { recorded, running, known } = dropped.thinkingLevel;
|
|
96
|
-
warnOnce(`${sessionId}\u0000thinking\u0000${settings.model.provider}/${settings.model.id}\u0000${recorded}`, known
|
|
97
|
-
? `[fastagent] session ${sessionId}: recorded thinking level "${recorded}" is not supported by ${settings.model.provider}/${settings.model.id} — running at "${running}"`
|
|
98
|
-
: `[fastagent] session ${sessionId}: recorded thinking level "${recorded}" is unknown — using the configured default`);
|
|
99
|
-
}
|
|
100
|
-
return { model: settings.model, thinkingLevel: settings.thinkingLevel };
|
|
101
|
-
}
|
|
102
|
-
export function resolveHarnessActiveToolNames(recorded, tools, sessionId) {
|
|
103
|
-
const anyDeferred = tools.some(isDeferredTool);
|
|
104
|
-
const initial = tools.filter((t) => !isDeferredTool(t)).map((t) => t.name);
|
|
105
|
-
if (recorded === null)
|
|
106
|
-
return anyDeferred ? initial : undefined;
|
|
107
|
-
const mounted = new Set(tools.map((t) => t.name));
|
|
108
|
-
const known = recorded.filter((name) => mounted.has(name));
|
|
109
|
-
const missing = recorded.filter((name) => !mounted.has(name));
|
|
110
|
-
if (missing.length > 0) {
|
|
111
|
-
const emit = warnedRestores.has(`${sessionId}\u0000${missing.join(",")}`) ? log.debug : log.warn;
|
|
112
|
-
warnedRestores.add(`${sessionId}\u0000${missing.join(",")}`);
|
|
113
|
-
emit(`[fastagent] session ${sessionId}: dropping recorded activation(s) no longer mounted: ${missing.join(", ")}`);
|
|
114
|
-
}
|
|
115
|
-
return [...new Set([...initial, ...known])];
|
|
116
|
-
}
|
|
117
|
-
/** Open-or-create the session per invoke: existing → open (history via buildContext); missing → create. */
|
|
118
|
-
export function piHarnessFactory(options) {
|
|
119
|
-
return async (sessionId) => {
|
|
120
|
-
const session = await options.sessions.openOrCreate(sessionId);
|
|
121
|
-
// One extra entry walk per invoke to collect the activation deltas — negligible against the model
|
|
122
|
-
// call, same trade as L2's per-invoke definition re-read. The walk is over the ACTIVE PATH, not
|
|
123
|
-
// the flat journal: `navigate` moves the leaf, so the tree can hold an abandoned branch whose
|
|
124
|
-
// activations and overrides this session has left behind.
|
|
125
|
-
const entries = await activePathEntries(session);
|
|
126
|
-
const activated = entries.flatMap((e) => e.type === "custom" && e.customType === TOOL_ACTIVATION_ENTRY
|
|
127
|
-
? (e.data?.names ?? [])
|
|
128
|
-
: []);
|
|
129
|
-
const fresh = options.live ? await options.live() : undefined;
|
|
130
|
-
const { systemPrompt } = options;
|
|
131
|
-
const prompt = fresh ? fresh.systemPrompt : typeof systemPrompt === "function" ? systemPrompt() : systemPrompt;
|
|
132
|
-
const skills = fresh ? fresh.skills : options.skills;
|
|
133
|
-
// Session overrides (set_model / set_thinking) win over the assembly defaults — same entry walk.
|
|
134
|
-
const overrides = resolveHarnessOverrides(entries, options.models, { model: options.model, thinkingLevel: options.thinkingLevel ?? DEFAULT_THINKING_LEVEL }, sessionId);
|
|
135
|
-
const harness = new AgentHarness({
|
|
136
|
-
// Static, not a per-turn provider: the env is fixed for the agent's lifetime, and resolving a
|
|
137
|
-
// constant per turn would only add a promise to the turn's critical path.
|
|
138
|
-
toolContext: { env: options.env },
|
|
139
|
-
session,
|
|
140
|
-
models: options.models,
|
|
141
|
-
model: overrides.model,
|
|
142
|
-
thinkingLevel: overrides.thinkingLevel,
|
|
143
|
-
tools: options.tools,
|
|
144
|
-
activeToolNames: resolveHarnessActiveToolNames(activated.length > 0 ? activated : null, options.tools ?? [], sessionId),
|
|
145
|
-
systemPrompt: prompt,
|
|
146
|
-
resources: skills ? { skills } : undefined,
|
|
147
|
-
streamOptions: { maxRetries: PROVIDER_MAX_RETRIES },
|
|
148
|
-
retry: SUMMARIZATION_RETRY_POLICY,
|
|
149
|
-
});
|
|
150
|
-
harnessSessions.set(harness, session);
|
|
151
|
-
return harness;
|
|
152
|
-
};
|
|
153
|
-
}
|