@bastani/atomic 0.9.26-alpha.4 → 0.9.26-alpha.5
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 +16 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +10 -0
- package/dist/builtin/workflows/builtin/{chunk-73p2cm5s.js → chunk-613yaa53.js} +124 -43
- package/dist/builtin/workflows/builtin/{chunk-n95myjcg.js → chunk-6kqrk0pf.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-ycvg8y8k.js → chunk-ea6nrbn3.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +317 -62
- package/dist/builtin/workflows/src/index.js +176 -62
- package/dist/core/agent-session-export.js +1 -1
- package/dist/core/agent-session-export.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +3 -3
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +3 -3
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +3 -1
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js +5 -0
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/loader-bindings.d.ts +1 -1
- package/dist/core/extensions/loader-bindings.d.ts.map +1 -1
- package/dist/core/extensions/loader-bindings.js +1 -0
- package/dist/core/extensions/loader-bindings.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +2 -1
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/tool-types.d.ts +3 -0
- package/dist/core/extensions/tool-types.d.ts.map +1 -1
- package/dist/core/extensions/tool-types.js.map +1 -1
- package/dist/core/extensions/ui-types.d.ts +2 -2
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/package-manager-auto-resources.d.ts.map +1 -1
- package/dist/core/package-manager-auto-resources.js +6 -2
- package/dist/core/package-manager-auto-resources.js.map +1 -1
- package/dist/core/package-manager-resolver.d.ts.map +1 -1
- package/dist/core/package-manager-resolver.js +4 -2
- package/dist/core/package-manager-resolver.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +7 -3
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-merge.d.ts.map +1 -1
- package/dist/core/settings-merge.js +10 -0
- package/dist/core/settings-merge.js.map +1 -1
- package/dist/core/settings-types.d.ts +7 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +20 -1
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +3 -1
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +19 -13
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +2 -3
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector-list.js +3 -1
- package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/config-selector-project-scope.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector-project-scope.js +2 -1
- package/dist/modes/interactive/components/config-selector-project-scope.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +2 -5
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +14 -40
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -3
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +6 -1
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +5 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +9 -0
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js +10 -1
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/utils/image-convert.d.ts +5 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +36 -6
- package/dist/utils/image-convert.js.map +1 -1
- package/docs/extensions.md +6 -0
- package/docs/providers.md +10 -0
- package/docs/settings.md +28 -1
- package/docs/workflows/operations.md +25 -3
- package/npm-shrinkwrap.json +71 -92
- package/package.json +8 -8
|
@@ -63,6 +63,92 @@ function raceAbort2(operation, signal) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// dist/builtin/workflows/src/durable/dbos-database-diagnostics.ts
|
|
67
|
+
function redactedDatabaseEndpoint(url) {
|
|
68
|
+
try {
|
|
69
|
+
const parsed = new URL(url);
|
|
70
|
+
parsed.username = "";
|
|
71
|
+
parsed.password = "";
|
|
72
|
+
parsed.search = "";
|
|
73
|
+
parsed.hash = "";
|
|
74
|
+
return parsed.toString();
|
|
75
|
+
} catch {
|
|
76
|
+
return "unparseable PostgreSQL endpoint";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function redactedDatabaseMessage(message, url) {
|
|
80
|
+
let safe = message.replace(/postgres(?:ql)?:\/\/[^\s"'<>]+/gi, (value) => redactedDatabaseEndpoint(value));
|
|
81
|
+
let configuredSecrets = [];
|
|
82
|
+
if (url !== undefined) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = new URL(url);
|
|
85
|
+
configuredSecrets = [parsed.username, parsed.password, ...parsed.searchParams.values()].flatMap((secret) => {
|
|
86
|
+
try {
|
|
87
|
+
return [secret, decodeURIComponent(secret)];
|
|
88
|
+
} catch {
|
|
89
|
+
return [secret];
|
|
90
|
+
}
|
|
91
|
+
}).filter((secret) => secret.length > 0);
|
|
92
|
+
} catch {
|
|
93
|
+
return "PostgreSQL diagnostic could not be safely redacted; check the configured endpoint.";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
safe = safe.replace(/\b(password|passwd|token|secret|sslpassword|user(?:name)?)\s*(?:([=:])\s*|((?:is|was)\s+)|\s+)(?:"([^"]*)"|'([^']*)'|([^\s,;]+))/gi, (match, key, separator, filler, doubleQuoted, singleQuoted, bare) => {
|
|
97
|
+
const value = doubleQuoted ?? singleQuoted ?? bare ?? "";
|
|
98
|
+
const isUserContext = /^user(?:name)?$/i.test(key);
|
|
99
|
+
if (separator === undefined && !isUserContext && !configuredSecrets.includes(value))
|
|
100
|
+
return match;
|
|
101
|
+
const rendered = doubleQuoted !== undefined ? '"[redacted]"' : singleQuoted !== undefined ? "'[redacted]'" : "[redacted]";
|
|
102
|
+
return `${key}${separator ?? " "}${filler ?? ""}${rendered}`;
|
|
103
|
+
});
|
|
104
|
+
for (const secret of new Set(configuredSecrets)) {
|
|
105
|
+
if (secret.length < 4)
|
|
106
|
+
continue;
|
|
107
|
+
const escaped = secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
108
|
+
const expression = new RegExp(`(?<![\\p{L}\\p{N}_\\[])${escaped}(?![\\p{L}\\p{N}_\\]])`, "gu");
|
|
109
|
+
safe = safe.replace(expression, "[redacted]");
|
|
110
|
+
}
|
|
111
|
+
return safe;
|
|
112
|
+
}
|
|
113
|
+
function databaseDependencyMessage(message, diagnostics) {
|
|
114
|
+
const safe = redactedDatabaseMessage(message, diagnostics?.url);
|
|
115
|
+
if (diagnostics === undefined)
|
|
116
|
+
return safe;
|
|
117
|
+
const failure = diagnostics.failure === undefined ? "" : ` Last probe/recovery failure: ${redactedDatabaseMessage(diagnostics.failure, diagnostics.url)}`;
|
|
118
|
+
return `${safe} Provider: ${diagnostics.provider}; endpoint: ${redactedDatabaseEndpoint(diagnostics.url)}.${failure}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// dist/builtin/workflows/src/durable/dbos-process-owner.ts
|
|
122
|
+
function emptyOwner() {
|
|
123
|
+
return {
|
|
124
|
+
version: 1,
|
|
125
|
+
state: "uninitialized",
|
|
126
|
+
configured: undefined,
|
|
127
|
+
active: undefined,
|
|
128
|
+
launchPromise: undefined,
|
|
129
|
+
shutdownPromise: undefined,
|
|
130
|
+
failure: undefined,
|
|
131
|
+
wrappers: undefined,
|
|
132
|
+
leases: new Set
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function ownerBag() {
|
|
136
|
+
return globalThis;
|
|
137
|
+
}
|
|
138
|
+
function getDbosProcessOwner() {
|
|
139
|
+
const bag = ownerBag();
|
|
140
|
+
const existing = bag[DBOS_PROCESS_OWNER_KEY];
|
|
141
|
+
if (existing !== undefined && existing.version === 1)
|
|
142
|
+
return existing;
|
|
143
|
+
const created = emptyOwner();
|
|
144
|
+
bag[DBOS_PROCESS_OWNER_KEY] = created;
|
|
145
|
+
return created;
|
|
146
|
+
}
|
|
147
|
+
var DBOS_PROCESS_OWNER_KEY;
|
|
148
|
+
var init_dbos_process_owner = __esm(() => {
|
|
149
|
+
DBOS_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/dbos-process-owner@1");
|
|
150
|
+
});
|
|
151
|
+
|
|
66
152
|
// dist/builtin/workflows/src/durable/dbos-admission.ts
|
|
67
153
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
68
154
|
function isDbosDependencyError(error) {
|
|
@@ -81,6 +167,8 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
|
|
|
81
167
|
return await raceAbort2(operation(controller.signal), controller.signal);
|
|
82
168
|
} catch (error) {
|
|
83
169
|
controller.abort(error);
|
|
170
|
+
if (isDbosDependencyError(error) && error.admissionDetail !== undefined)
|
|
171
|
+
throw new DbosDependencyError(error.admissionDetail, null);
|
|
84
172
|
throw error;
|
|
85
173
|
} finally {
|
|
86
174
|
clearTimeout(timer);
|
|
@@ -89,10 +177,13 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
|
|
|
89
177
|
}
|
|
90
178
|
var DBOS_ADMISSION_TIMEOUT_MS = 1e4, DbosDependencyError, key2, bag, dbosAdmissionContext;
|
|
91
179
|
var init_dbos_admission = __esm(() => {
|
|
180
|
+
init_dbos_process_owner();
|
|
92
181
|
DbosDependencyError = class DbosDependencyError extends Error {
|
|
93
182
|
code = "ATOMIC_DBOS_DEPENDENCY";
|
|
94
|
-
|
|
95
|
-
|
|
183
|
+
admissionDetail;
|
|
184
|
+
constructor(message = "Workflow database unavailable during admission. Restore PostgreSQL before retrying.", diagnostics = getDbosProcessOwner().databaseDiagnostics?.(), admissionDetail) {
|
|
185
|
+
super(databaseDependencyMessage(message, diagnostics ?? undefined));
|
|
186
|
+
this.admissionDetail = admissionDetail === undefined ? undefined : redactedDatabaseMessage(admissionDetail);
|
|
96
187
|
this.name = "DbosDependencyError";
|
|
97
188
|
}
|
|
98
189
|
};
|
|
@@ -30263,11 +30354,11 @@ function fenceDbosAdmissionPool(pool) {
|
|
|
30263
30354
|
const connect = pool.connect.bind(pool);
|
|
30264
30355
|
async function acquire(signal) {
|
|
30265
30356
|
if (signal.aborted)
|
|
30266
|
-
throw
|
|
30357
|
+
throw sdkDependencyError();
|
|
30267
30358
|
const pending = connect().then((client) => {
|
|
30268
30359
|
if (signal.aborted) {
|
|
30269
30360
|
client.release(true);
|
|
30270
|
-
throw
|
|
30361
|
+
throw sdkDependencyError();
|
|
30271
30362
|
}
|
|
30272
30363
|
return fencedClient(client, signal);
|
|
30273
30364
|
});
|
|
@@ -30311,7 +30402,7 @@ function fencedClient(client, signal) {
|
|
|
30311
30402
|
const callback = typeof last === "function" ? values.pop() : undefined;
|
|
30312
30403
|
const pending = (async () => {
|
|
30313
30404
|
if (signal.aborted || released)
|
|
30314
|
-
throw
|
|
30405
|
+
throw sdkDependencyError();
|
|
30315
30406
|
try {
|
|
30316
30407
|
return await raceAbort2(new Promise((resolve, reject) => {
|
|
30317
30408
|
Reflect.apply(target, client, [
|
|
@@ -30343,9 +30434,15 @@ function fencedClient(client, signal) {
|
|
|
30343
30434
|
}
|
|
30344
30435
|
});
|
|
30345
30436
|
}
|
|
30437
|
+
function sdkDependencyError(message) {
|
|
30438
|
+
const reported = message === undefined ? new DbosDependencyError : new DbosDependencyError(message, null);
|
|
30439
|
+
return new DbosDependencyError(undefined, null, reported.message);
|
|
30440
|
+
}
|
|
30346
30441
|
function databaseError(error, signal) {
|
|
30347
30442
|
if (signal.aborted)
|
|
30348
|
-
return
|
|
30443
|
+
return sdkDependencyError();
|
|
30444
|
+
if (isDbosDependencyError(error))
|
|
30445
|
+
return sdkDependencyError(error.admissionDetail ?? error.message);
|
|
30349
30446
|
const pending = [error];
|
|
30350
30447
|
const seen = new Set;
|
|
30351
30448
|
while (pending.length > 0) {
|
|
@@ -30362,7 +30459,7 @@ function databaseError(error, signal) {
|
|
|
30362
30459
|
const code = "code" in value && typeof value.code === "string" ? value.code : undefined;
|
|
30363
30460
|
const message = value instanceof Error ? value.message : "";
|
|
30364
30461
|
if (code !== undefined && (/^(?:08|53|57)[0-9A-Z]{3}$|^40003$/.test(code) || connectionErrnos.has(code)) || code === undefined && connectionMessages.has(message)) {
|
|
30365
|
-
return
|
|
30462
|
+
return sdkDependencyError();
|
|
30366
30463
|
}
|
|
30367
30464
|
}
|
|
30368
30465
|
return error;
|
|
@@ -30385,7 +30482,9 @@ var init_dbos_admission_pool = __esm(() => {
|
|
|
30385
30482
|
"Connection terminated unexpectedly",
|
|
30386
30483
|
"Connection terminated due to connection timeout",
|
|
30387
30484
|
"Client has encountered a connection error and is not queryable",
|
|
30388
|
-
"timeout exceeded when trying to connect"
|
|
30485
|
+
"timeout exceeded when trying to connect",
|
|
30486
|
+
"Client was closed and is not queryable",
|
|
30487
|
+
"Postgres connection pool changed while acquiring a connection"
|
|
30389
30488
|
]);
|
|
30390
30489
|
});
|
|
30391
30490
|
|
|
@@ -30673,6 +30772,11 @@ function defaultDatabaseUrl(name) {
|
|
|
30673
30772
|
function configureAdmissionDatabase(sdk, config, launchLock = withDbosLaunchLock) {
|
|
30674
30773
|
const systemDatabaseUrl = config.systemDatabaseUrl ?? defaultDatabaseUrl(config.name);
|
|
30675
30774
|
const health = resolvedPostgresHealth(systemDatabaseUrl);
|
|
30775
|
+
getDbosProcessOwner().databaseDiagnostics = () => ({
|
|
30776
|
+
provider: health === undefined ? config.systemDatabaseUrl === undefined ? "docker" : "configured" : "managed",
|
|
30777
|
+
url: health?.endpoint ?? systemDatabaseUrl,
|
|
30778
|
+
failure: health?.lastFailure?.message
|
|
30779
|
+
});
|
|
30676
30780
|
const createPool = () => {
|
|
30677
30781
|
let unsubscribe;
|
|
30678
30782
|
const managed = createRecoverablePostgresPool(systemDatabaseUrl, {
|
|
@@ -30710,6 +30814,7 @@ var import_datasource2;
|
|
|
30710
30814
|
var init_dbos_admission_config = __esm(() => {
|
|
30711
30815
|
init_dbos_admission_pool();
|
|
30712
30816
|
init_dbos_launch_lock();
|
|
30817
|
+
init_dbos_process_owner();
|
|
30713
30818
|
init_dbos_recoverable_pool();
|
|
30714
30819
|
import_datasource2 = __toESM(require_datasource(), 1);
|
|
30715
30820
|
});
|
|
@@ -37791,10 +37896,11 @@ function hasInvocationData(checkpoints, replayKey) {
|
|
|
37791
37896
|
|
|
37792
37897
|
// dist/builtin/workflows/src/engine/run.ts
|
|
37793
37898
|
init_dbos_admission();
|
|
37899
|
+
init_dbos_process_owner();
|
|
37794
37900
|
|
|
37795
37901
|
// dist/builtin/workflows/src/durable/backend-process-owner.ts
|
|
37796
37902
|
var DURABLE_BACKEND_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/durable-backend-process-owner@1");
|
|
37797
|
-
function
|
|
37903
|
+
function emptyOwner2() {
|
|
37798
37904
|
return {
|
|
37799
37905
|
version: 1,
|
|
37800
37906
|
injectedBackend: undefined,
|
|
@@ -37804,15 +37910,15 @@ function emptyOwner() {
|
|
|
37804
37910
|
warningReported: false
|
|
37805
37911
|
};
|
|
37806
37912
|
}
|
|
37807
|
-
function
|
|
37913
|
+
function ownerBag2() {
|
|
37808
37914
|
return globalThis;
|
|
37809
37915
|
}
|
|
37810
37916
|
function getDurableBackendProcessOwner() {
|
|
37811
|
-
const bag =
|
|
37917
|
+
const bag = ownerBag2();
|
|
37812
37918
|
const existing = bag[DURABLE_BACKEND_PROCESS_OWNER_KEY];
|
|
37813
37919
|
if (existing !== undefined && existing.version === 1)
|
|
37814
37920
|
return existing;
|
|
37815
|
-
const created =
|
|
37921
|
+
const created = emptyOwner2();
|
|
37816
37922
|
bag[DURABLE_BACKEND_PROCESS_OWNER_KEY] = created;
|
|
37817
37923
|
return created;
|
|
37818
37924
|
}
|
|
@@ -39024,33 +39130,8 @@ function classifyDbosDeletionTombstone(records, workflowId) {
|
|
|
39024
39130
|
return isCurrentDurableFormat(raw.version) ? "current" : "unknown";
|
|
39025
39131
|
}
|
|
39026
39132
|
|
|
39027
|
-
// dist/builtin/workflows/src/durable/dbos-
|
|
39028
|
-
|
|
39029
|
-
function emptyOwner2() {
|
|
39030
|
-
return {
|
|
39031
|
-
version: 1,
|
|
39032
|
-
state: "uninitialized",
|
|
39033
|
-
configured: undefined,
|
|
39034
|
-
active: undefined,
|
|
39035
|
-
launchPromise: undefined,
|
|
39036
|
-
shutdownPromise: undefined,
|
|
39037
|
-
failure: undefined,
|
|
39038
|
-
wrappers: undefined,
|
|
39039
|
-
leases: new Set
|
|
39040
|
-
};
|
|
39041
|
-
}
|
|
39042
|
-
function ownerBag2() {
|
|
39043
|
-
return globalThis;
|
|
39044
|
-
}
|
|
39045
|
-
function getDbosProcessOwner() {
|
|
39046
|
-
const bag = ownerBag2();
|
|
39047
|
-
const existing = bag[DBOS_PROCESS_OWNER_KEY];
|
|
39048
|
-
if (existing !== undefined && existing.version === 1)
|
|
39049
|
-
return existing;
|
|
39050
|
-
const created = emptyOwner2();
|
|
39051
|
-
bag[DBOS_PROCESS_OWNER_KEY] = created;
|
|
39052
|
-
return created;
|
|
39053
|
-
}
|
|
39133
|
+
// dist/builtin/workflows/src/durable/dbos-backend.ts
|
|
39134
|
+
init_dbos_process_owner();
|
|
39054
39135
|
|
|
39055
39136
|
// dist/builtin/workflows/src/durable/dbos-sdk-handle.ts
|
|
39056
39137
|
var ATOMIC_EXECUTOR_ID = `atomic-${process.pid.toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
|
|
@@ -39171,6 +39252,7 @@ function statusToInfo(status, fallbackId) {
|
|
|
39171
39252
|
}
|
|
39172
39253
|
|
|
39173
39254
|
// dist/builtin/workflows/src/durable/dbos-system-database-url.ts
|
|
39255
|
+
init_dbos_process_owner();
|
|
39174
39256
|
function nonEmptyTrimmed(value) {
|
|
39175
39257
|
const trimmed = value?.trim();
|
|
39176
39258
|
return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;
|
|
@@ -39185,9 +39267,7 @@ class DbosSystemDatabaseConflictError extends Error {
|
|
|
39185
39267
|
function redactDatabaseUrl(url) {
|
|
39186
39268
|
try {
|
|
39187
39269
|
const parsed = new URL(url);
|
|
39188
|
-
|
|
39189
|
-
parsed.password = "***";
|
|
39190
|
-
return parsed.toString();
|
|
39270
|
+
return parsed.host;
|
|
39191
39271
|
} catch {
|
|
39192
39272
|
return "the requested database";
|
|
39193
39273
|
}
|
|
@@ -40904,6 +40984,7 @@ class PostgresHealth {
|
|
|
40904
40984
|
attempts = 0;
|
|
40905
40985
|
nextRecoveryAt = 0;
|
|
40906
40986
|
failure;
|
|
40987
|
+
healthySinceFailure = false;
|
|
40907
40988
|
revision = 0;
|
|
40908
40989
|
listeners = new Set;
|
|
40909
40990
|
constructor(operations) {
|
|
@@ -40912,6 +40993,18 @@ class PostgresHealth {
|
|
|
40912
40993
|
get lastFailure() {
|
|
40913
40994
|
return this.failure;
|
|
40914
40995
|
}
|
|
40996
|
+
get endpoint() {
|
|
40997
|
+
return this.operations.url?.();
|
|
40998
|
+
}
|
|
40999
|
+
retainFailure(error) {
|
|
41000
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
41001
|
+
const safe = redactedDatabaseMessage(message, this.endpoint);
|
|
41002
|
+
this.failure = new Error(safe);
|
|
41003
|
+
this.healthySinceFailure = false;
|
|
41004
|
+
}
|
|
41005
|
+
dependencyFailure(message) {
|
|
41006
|
+
return new DbosDependencyError(message, this.endpoint === undefined ? undefined : { provider: "managed", url: this.endpoint, failure: this.failure?.message });
|
|
41007
|
+
}
|
|
40915
41008
|
subscribe(listener) {
|
|
40916
41009
|
this.listeners.add(listener);
|
|
40917
41010
|
return () => this.listeners.delete(listener);
|
|
@@ -40934,12 +41027,15 @@ class PostgresHealth {
|
|
|
40934
41027
|
await this.operations.validate?.(client);
|
|
40935
41028
|
}
|
|
40936
41029
|
} catch (error) {
|
|
40937
|
-
this.
|
|
41030
|
+
this.retainFailure(error);
|
|
40938
41031
|
if (!isQueryReadTimeout(error)) {
|
|
40939
41032
|
this.invalidate();
|
|
40940
|
-
|
|
41033
|
+
if (this.endpoint === undefined)
|
|
41034
|
+
throw error;
|
|
41035
|
+
const failure = this.dependencyFailure("Managed PostgreSQL connection validation refused. Preserve its data and ownership records.");
|
|
41036
|
+
throw error instanceof DbosDependencyError ? failure : new Error(failure.message);
|
|
40941
41037
|
}
|
|
40942
|
-
throw
|
|
41038
|
+
throw this.dependencyFailure("Managed PostgreSQL did not answer a connection identity check in time.");
|
|
40943
41039
|
}
|
|
40944
41040
|
}
|
|
40945
41041
|
check() {
|
|
@@ -40980,7 +41076,7 @@ class PostgresHealth {
|
|
|
40980
41076
|
} catch (retryError) {
|
|
40981
41077
|
if (!isMonitoringConnectionFailure(retryError))
|
|
40982
41078
|
throw retryError;
|
|
40983
|
-
this.
|
|
41079
|
+
this.retainFailure(retryError);
|
|
40984
41080
|
return;
|
|
40985
41081
|
}
|
|
40986
41082
|
}
|
|
@@ -40995,6 +41091,7 @@ class PostgresHealth {
|
|
|
40995
41091
|
this.available = identity;
|
|
40996
41092
|
this.attempts = 0;
|
|
40997
41093
|
this.nextRecoveryAt = 0;
|
|
41094
|
+
this.healthySinceFailure = true;
|
|
40998
41095
|
return identity.url;
|
|
40999
41096
|
}
|
|
41000
41097
|
async refresh() {
|
|
@@ -41004,19 +41101,21 @@ class PostgresHealth {
|
|
|
41004
41101
|
return ready;
|
|
41005
41102
|
} catch (error) {
|
|
41006
41103
|
if (isQueryReadTimeout(error)) {
|
|
41007
|
-
this.
|
|
41008
|
-
throw this.
|
|
41104
|
+
this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
|
|
41105
|
+
throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
|
|
41009
41106
|
}
|
|
41010
|
-
this.
|
|
41107
|
+
this.retainFailure(error);
|
|
41011
41108
|
if (!(error instanceof Error && ("code" in error) && error.code === "53300"))
|
|
41012
41109
|
this.invalidate();
|
|
41013
|
-
throw error;
|
|
41110
|
+
throw this.endpoint === undefined ? error : this.dependencyFailure("Managed PostgreSQL recovery refused after a health probe failure. Preserve its data and ownership records.");
|
|
41111
|
+
}
|
|
41112
|
+
if (this.attempts === 0 && (this.failure === undefined || this.healthySinceFailure)) {
|
|
41113
|
+
this.retainFailure(new Error("Managed PostgreSQL failed its live health check."));
|
|
41114
|
+
this.healthySinceFailure = false;
|
|
41014
41115
|
}
|
|
41015
|
-
if (this.attempts === 0)
|
|
41016
|
-
this.failure = new DbosDependencyError("Managed PostgreSQL failed its live health check.");
|
|
41017
41116
|
this.invalidate();
|
|
41018
41117
|
if ((this.operations.now ?? Date.now)() < this.nextRecoveryAt)
|
|
41019
|
-
throw
|
|
41118
|
+
throw this.dependencyFailure("Managed Postgres recovery is cooling down after bounded attempts.");
|
|
41020
41119
|
while (!this.stopped && this.attempts < RECOVERY_ATTEMPTS) {
|
|
41021
41120
|
const attempt = this.attempts++;
|
|
41022
41121
|
if (attempt > 0)
|
|
@@ -41029,12 +41128,12 @@ class PostgresHealth {
|
|
|
41029
41128
|
if (ready !== undefined)
|
|
41030
41129
|
return ready;
|
|
41031
41130
|
} catch (error) {
|
|
41032
|
-
this.
|
|
41131
|
+
this.retainFailure(error);
|
|
41033
41132
|
}
|
|
41034
41133
|
}
|
|
41035
41134
|
this.attempts = 0;
|
|
41036
41135
|
this.nextRecoveryAt = (this.operations.now ?? Date.now)() + HEALTH_INTERVAL_MS;
|
|
41037
|
-
throw
|
|
41136
|
+
throw this.dependencyFailure("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
|
|
41038
41137
|
}
|
|
41039
41138
|
}
|
|
41040
41139
|
|
|
@@ -41690,6 +41789,8 @@ async function ensureCluster(options = {}) {
|
|
|
41690
41789
|
const server = current.server;
|
|
41691
41790
|
if (!server)
|
|
41692
41791
|
throw new Error("Managed Postgres published identity is missing.");
|
|
41792
|
+
if (managedPostmaster(current) === undefined)
|
|
41793
|
+
return;
|
|
41693
41794
|
if (!managedPostgresRuntimeHealthy(current, server.port)) {
|
|
41694
41795
|
verifyManagedPostmasterProcess(current, server);
|
|
41695
41796
|
return;
|
|
@@ -41706,6 +41807,7 @@ async function ensureCluster(options = {}) {
|
|
|
41706
41807
|
};
|
|
41707
41808
|
health = new PostgresHealth({
|
|
41708
41809
|
probe: () => inspect(),
|
|
41810
|
+
url: embeddedDbosSystemDatabaseUrl,
|
|
41709
41811
|
validate: async (client) => {
|
|
41710
41812
|
const identity = await inspect(async () => {
|
|
41711
41813
|
const query = { text: POSTGRES_IDENTITY_SQL, query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS };
|
|
@@ -42793,6 +42895,9 @@ async function requireDockerSuccess(action, args) {
|
|
|
42793
42895
|
throw new Error(`Could not ${action}: ${commandFailureDetail(result)}`);
|
|
42794
42896
|
}
|
|
42795
42897
|
|
|
42898
|
+
// dist/builtin/workflows/src/durable/dbos-lifecycle.ts
|
|
42899
|
+
init_dbos_process_owner();
|
|
42900
|
+
|
|
42796
42901
|
// dist/builtin/workflows/src/durable/dbos-registration-diagnostics.ts
|
|
42797
42902
|
var cachedErrorModule;
|
|
42798
42903
|
var errorModuleLoad;
|
|
@@ -55743,7 +55848,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
55743
55848
|
if (control === latestControl && !ownController.signal.aborted && isDbosDependencyError(error)) {
|
|
55744
55849
|
activeStore.recordRunExecutionState(runId, {
|
|
55745
55850
|
phase: "blocked_dependency",
|
|
55746
|
-
dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed
|
|
55851
|
+
dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed. ${error.message}`
|
|
55747
55852
|
});
|
|
55748
55853
|
if (status === "paused")
|
|
55749
55854
|
return;
|
|
@@ -55790,7 +55895,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
55790
55895
|
if (!admission.admitting)
|
|
55791
55896
|
return pausePersistence;
|
|
55792
55897
|
backgroundAdmissionControl(durableBackend, runId, pausePersistence, (error, resumable) => {
|
|
55793
|
-
admissionControlError = unknownErrorMessage(error);
|
|
55898
|
+
admissionControlError = databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.());
|
|
55794
55899
|
runSnapshot.error = admissionControlError;
|
|
55795
55900
|
activeStore.recordRunPaused(runId, undefined, { resumable });
|
|
55796
55901
|
return runSnapshot.error;
|
|
@@ -55807,7 +55912,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
55807
55912
|
} catch (error) {
|
|
55808
55913
|
if (admission.failed) {
|
|
55809
55914
|
scheduler.releaseRun();
|
|
55810
|
-
throw error;
|
|
55915
|
+
throw new Error(admissionControlError ?? databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.()));
|
|
55811
55916
|
}
|
|
55812
55917
|
}
|
|
55813
55918
|
if (generation !== pauseGeneration)
|
|
@@ -55880,12 +55985,21 @@ async function run(def, inputs, opts = {}) {
|
|
|
55880
55985
|
}).catch((error) => {
|
|
55881
55986
|
const isTopologyError = typeof error === "object" && error !== null && "name" in error && error.name === "DurableNestedTopologyError";
|
|
55882
55987
|
if (!isDbosDependencyError(error) && !isTopologyError) {
|
|
55883
|
-
|
|
55884
|
-
|
|
55988
|
+
const admissionDetail = unknownErrorMessage(error);
|
|
55989
|
+
const diagnostics = getDbosProcessOwner().databaseDiagnostics?.();
|
|
55990
|
+
const safeMessage = databaseDependencyMessage(admissionDetail, diagnostics);
|
|
55991
|
+
activeStore.recordRunExecutionState(runId, {
|
|
55992
|
+
phase: "blocked_dependency",
|
|
55993
|
+
dependencyError: safeMessage
|
|
55994
|
+
});
|
|
55995
|
+
const safeError = new Error(safeMessage);
|
|
55996
|
+
durableAdmissionFailure = { error: safeError };
|
|
55997
|
+
classifiedFailures.set(safeError, classifyWorkflowFailure({
|
|
55885
55998
|
code: "ATOMIC_DURABLE_ADMISSION_REJECTED",
|
|
55886
|
-
message:
|
|
55887
|
-
cause:
|
|
55999
|
+
message: safeMessage,
|
|
56000
|
+
cause: safeError
|
|
55888
56001
|
}));
|
|
56002
|
+
throw safeError;
|
|
55889
56003
|
}
|
|
55890
56004
|
throw error;
|
|
55891
56005
|
}), ownController.signal);
|
|
@@ -114,7 +114,7 @@ export async function exportToHtml(outputPath, options = {}) {
|
|
|
114
114
|
]);
|
|
115
115
|
// Create tool renderer if we have an extension runner (for custom tool HTML rendering)
|
|
116
116
|
const toolRenderer = createToolHtmlRenderer({
|
|
117
|
-
|
|
117
|
+
getToolRenderers: (name) => this.extensionRunner.resolveToolRenderers(name, () => this.getToolDefinition(name)),
|
|
118
118
|
theme,
|
|
119
119
|
cwd: this.sessionManager.getCwd(),
|
|
120
120
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-export.js","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage, Usage } from \"@bastani/pi-ai/compat\";\nimport { getThemeByName, theme } from \"../modes/interactive/theme/theme.js\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.js\";\nimport { calculateContextTokens, estimateProjectedContextTokens } from \"./compaction/index.ts\";\nimport type { ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.js\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport { addUsageToTotals, createUsageTotals } from \"./usage-totals.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tlet userMessages = 0;\n\tlet assistantMessages = 0;\n\tlet toolResults = 0;\n\tlet totalMessages = 0;\n\tlet toolCalls = 0;\n\tconst totals = createUsageTotals();\n\tlet latestAssistantUsage: Usage | undefined;\n\tfor (const entry of this.sessionManager.getEntries()) {\n\t\tif (\n\t\t\t(entry.type === \"usage\" ||\n\t\t\t\tentry.type === \"branch_summary\" ||\n\t\t\t\tentry.type === \"session_summary\" ||\n\t\t\t\tentry.type === \"compaction\") &&\n\t\t\tentry.usage\n\t\t) {\n\t\t\taddUsageToTotals(totals, entry.usage);\n\t\t}\n\t\tif (entry.type !== \"message\") continue;\n\t\ttotalMessages++;\n\t\tconst message = entry.message;\n\t\tif (message.role === \"user\") userMessages++;\n\t\telse if (message.role === \"toolResult\") {\n\t\t\ttoolResults++;\n\t\t\tif (\"usage\" in message && message.usage) addUsageToTotals(totals, message.usage);\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tassistantMessages++;\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\ttoolCalls += assistant.content.filter((content) => content.type === \"toolCall\").length;\n\t\t\taddUsageToTotals(totals, assistant.usage);\n\t\t\tlatestAssistantUsage = assistant.usage;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages,\n\t\ttokens: {\n\t\t\tinput: totals.input,\n\t\t\toutput: totals.output,\n\t\t\tcacheRead: totals.cacheRead,\n\t\t\tcacheWrite: totals.cacheWrite,\n\t\t\ttotal: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t\t},\n\t\tcost: totals.cost,\n\t\tcontextUsage: this.getContextUsage(),\n\t\tlatestAssistantUsage,\n\t};\n}\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst projection = this.sessionManager.buildSessionProjection();\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Only a projected (not omitted) assistant that responded after the boundary\n\t\t// carries trustworthy usage.\n\t\tconst projectedAssistants = new Set(\n\t\t\tprojection.entries.flatMap((entry) =>\n\t\t\t\tentry.messages.some(\n\t\t\t\t\t(message) =>\n\t\t\t\t\t\tmessage.role === \"assistant\" &&\n\t\t\t\t\t\tmessage.stopReason !== \"aborted\" &&\n\t\t\t\t\t\tmessage.stopReason !== \"error\" &&\n\t\t\t\t\t\tcalculateContextTokens(message.usage, message.api) > 0,\n\t\t\t\t)\n\t\t\t\t\t? [entry.sourceEntry.id]\n\t\t\t\t\t: [],\n\t\t\t),\n\t\t);\n\t\tconst compactionIndex = branchEntries.findIndex((entry) => entry.id === latestCompactionBoundary.id);\n\t\tconst hasPostCompactionUsage = branchEntries\n\t\t\t.slice(compactionIndex + 1)\n\t\t\t.some((entry) => projectedAssistants.has(entry.id));\n\t\tif (!hasPostCompactionUsage) return { tokens: null, contextWindow, percent: null };\n\t}\n\n\tconst estimate = estimateProjectedContextTokens(projection, branchEntries);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @param options Optional export presentation settings; `themeName` overrides the\n * saved theme setting (e.g. with this run's --use-theme selection) when it names a\n * registered theme.\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(\n\tthis: AgentSession,\n\toutputPath?: string,\n\toptions: { themeName?: string } = {},\n): Promise<string> {\n\tconst themeName = [options.themeName, this.settingsManager.getTheme()].find(\n\t\t(candidate) => candidate !== undefined && getThemeByName(candidate) !== undefined,\n\t);\n\tconst [{ exportSessionToHtml }, { createToolHtmlRenderer }] = await Promise.all([\n\t\timport(\"./export-html/index.ts\"),\n\t\timport(\"./export-html/tool-renderer.ts\"),\n\t]);\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolDefinition: (name) => this.getToolDefinition(name),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(\n\tthis: AgentSession,\n\toutputPath?: string,\n\toptions: { includeShareContext?: boolean } = {},\n): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\tif (options.includeShareContext) {\n\t\tconst shareEntry = {\n\t\t\ttype: \"custom\",\n\t\t\tid: randomUUID(),\n\t\t\tparentId: prevId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType: \"atomic.share\",\n\t\t\tdata: {\n\t\t\t\tsystemPrompt: this.systemPrompt,\n\t\t\t\ttools: this.agent.state.tools.map(({ name, description, parameters }) => ({\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\tparameters,\n\t\t\t\t})),\n\t\t\t},\n\t\t};\n\t\tlines.push(JSON.stringify(shareEntry));\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tfor (const message of this.messages.slice().reverse()) {\n\t\tif (message.role !== \"assistant\") continue;\n\t\tconst assistant = message as AssistantMessage;\n\t\t// Skip aborted messages with no content\n\t\tif (assistant.stopReason === \"aborted\" && assistant.content.length === 0) continue;\n\t\tlet text = \"\";\n\t\tfor (const content of assistant.content) {\n\t\t\tif (content.type === \"text\") text += content.text;\n\t\t}\n\t\tconst trimmed = text.trim();\n\t\tif (trimmed) return trimmed;\n\t}\n\treturn undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"agent-session-export.js","sourceRoot":"","sources":["../../src/core/agent-session-export.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AssistantMessage, Usage } from \"@bastani/pi-ai/compat\";\nimport { getThemeByName, theme } from \"../modes/interactive/theme/theme.js\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { SessionStats } from \"./agent-session-types.js\";\nimport { calculateContextTokens, estimateProjectedContextTokens } from \"./compaction/index.ts\";\nimport type { ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport type { ContextUsage, ReplacedSessionContext } from \"./extensions/index.js\";\nimport { CURRENT_SESSION_VERSION, getLatestCompactionBoundaryEntry, type SessionHeader } from \"./session-manager.ts\";\nimport { addUsageToTotals, createUsageTotals } from \"./usage-totals.ts\";\n\nexport function getSessionStats(this: AgentSession): SessionStats {\n\tlet userMessages = 0;\n\tlet assistantMessages = 0;\n\tlet toolResults = 0;\n\tlet totalMessages = 0;\n\tlet toolCalls = 0;\n\tconst totals = createUsageTotals();\n\tlet latestAssistantUsage: Usage | undefined;\n\tfor (const entry of this.sessionManager.getEntries()) {\n\t\tif (\n\t\t\t(entry.type === \"usage\" ||\n\t\t\t\tentry.type === \"branch_summary\" ||\n\t\t\t\tentry.type === \"session_summary\" ||\n\t\t\t\tentry.type === \"compaction\") &&\n\t\t\tentry.usage\n\t\t) {\n\t\t\taddUsageToTotals(totals, entry.usage);\n\t\t}\n\t\tif (entry.type !== \"message\") continue;\n\t\ttotalMessages++;\n\t\tconst message = entry.message;\n\t\tif (message.role === \"user\") userMessages++;\n\t\telse if (message.role === \"toolResult\") {\n\t\t\ttoolResults++;\n\t\t\tif (\"usage\" in message && message.usage) addUsageToTotals(totals, message.usage);\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tassistantMessages++;\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\ttoolCalls += assistant.content.filter((content) => content.type === \"toolCall\").length;\n\t\t\taddUsageToTotals(totals, assistant.usage);\n\t\t\tlatestAssistantUsage = assistant.usage;\n\t\t}\n\t}\n\n\treturn {\n\t\tsessionFile: this.sessionFile,\n\t\tsessionId: this.sessionId,\n\t\tuserMessages,\n\t\tassistantMessages,\n\t\ttoolCalls,\n\t\ttoolResults,\n\t\ttotalMessages,\n\t\ttokens: {\n\t\t\tinput: totals.input,\n\t\t\toutput: totals.output,\n\t\t\tcacheRead: totals.cacheRead,\n\t\t\tcacheWrite: totals.cacheWrite,\n\t\t\ttotal: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t\t},\n\t\tcost: totals.cost,\n\t\tcontextUsage: this.getContextUsage(),\n\t\tlatestAssistantUsage,\n\t};\n}\n\nexport function getContextUsage(this: AgentSession): ContextUsage | undefined {\n\tconst model = this.model;\n\tif (!model) return undefined;\n\n\tconst contextWindow = model.contextWindow ?? 0;\n\tif (contextWindow <= 0) return undefined;\n\n\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t// We can only trust usage from an assistant that responded after the latest compaction.\n\t// If no such assistant exists, context token count is unknown until the next LLM response.\n\tconst projection = this.sessionManager.buildSessionProjection();\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst latestCompactionBoundary = getLatestCompactionBoundaryEntry(branchEntries);\n\n\tif (latestCompactionBoundary) {\n\t\t// Only a projected (not omitted) assistant that responded after the boundary\n\t\t// carries trustworthy usage.\n\t\tconst projectedAssistants = new Set(\n\t\t\tprojection.entries.flatMap((entry) =>\n\t\t\t\tentry.messages.some(\n\t\t\t\t\t(message) =>\n\t\t\t\t\t\tmessage.role === \"assistant\" &&\n\t\t\t\t\t\tmessage.stopReason !== \"aborted\" &&\n\t\t\t\t\t\tmessage.stopReason !== \"error\" &&\n\t\t\t\t\t\tcalculateContextTokens(message.usage, message.api) > 0,\n\t\t\t\t)\n\t\t\t\t\t? [entry.sourceEntry.id]\n\t\t\t\t\t: [],\n\t\t\t),\n\t\t);\n\t\tconst compactionIndex = branchEntries.findIndex((entry) => entry.id === latestCompactionBoundary.id);\n\t\tconst hasPostCompactionUsage = branchEntries\n\t\t\t.slice(compactionIndex + 1)\n\t\t\t.some((entry) => projectedAssistants.has(entry.id));\n\t\tif (!hasPostCompactionUsage) return { tokens: null, contextWindow, percent: null };\n\t}\n\n\tconst estimate = estimateProjectedContextTokens(projection, branchEntries);\n\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\treturn {\n\t\ttokens: estimate.tokens,\n\t\tcontextWindow,\n\t\tpercent,\n\t};\n}\n\n/**\n * Export session to HTML.\n * @param outputPath Optional output path (defaults to session directory)\n * @param options Optional export presentation settings; `themeName` overrides the\n * saved theme setting (e.g. with this run's --use-theme selection) when it names a\n * registered theme.\n * @returns Path to exported file\n */\n\nexport async function exportToHtml(\n\tthis: AgentSession,\n\toutputPath?: string,\n\toptions: { themeName?: string } = {},\n): Promise<string> {\n\tconst themeName = [options.themeName, this.settingsManager.getTheme()].find(\n\t\t(candidate) => candidate !== undefined && getThemeByName(candidate) !== undefined,\n\t);\n\tconst [{ exportSessionToHtml }, { createToolHtmlRenderer }] = await Promise.all([\n\t\timport(\"./export-html/index.ts\"),\n\t\timport(\"./export-html/tool-renderer.ts\"),\n\t]);\n\n\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\tgetToolRenderers: (name) => this.extensionRunner.resolveToolRenderers(name, () => this.getToolDefinition(name)),\n\t\ttheme,\n\t\tcwd: this.sessionManager.getCwd(),\n\t});\n\n\treturn await exportSessionToHtml(this.sessionManager, this.state, {\n\t\toutputPath,\n\t\tthemeName,\n\t\ttoolRenderer,\n\t});\n}\n\n/**\n * Export the current session branch to a JSONL file.\n * Writes the session header followed by all entries on the current branch path.\n * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n * @returns The resolved output file path.\n */\n\nexport function exportToJsonl(\n\tthis: AgentSession,\n\toutputPath?: string,\n\toptions: { includeShareContext?: boolean } = {},\n): string {\n\tconst filePath = resolvePath(\n\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\tprocess.cwd(),\n\t);\n\tconst dir = dirname(filePath);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\tconst header: SessionHeader = {\n\t\ttype: \"session\",\n\t\tversion: CURRENT_SESSION_VERSION,\n\t\tid: this.sessionManager.getSessionId(),\n\t\ttimestamp: new Date().toISOString(),\n\t\tcwd: this.sessionManager.getCwd(),\n\t};\n\n\tconst branchEntries = this.sessionManager.getBranch();\n\tconst lines = [JSON.stringify(header)];\n\n\t// Re-chain parentIds to form a linear sequence\n\tlet prevId: string | null = null;\n\tfor (const entry of branchEntries) {\n\t\tconst linear = { ...entry, parentId: prevId };\n\t\tlines.push(JSON.stringify(linear));\n\t\tprevId = entry.id;\n\t}\n\tif (options.includeShareContext) {\n\t\tconst shareEntry = {\n\t\t\ttype: \"custom\",\n\t\t\tid: randomUUID(),\n\t\t\tparentId: prevId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType: \"atomic.share\",\n\t\t\tdata: {\n\t\t\t\tsystemPrompt: this.systemPrompt,\n\t\t\t\ttools: this.agent.state.tools.map(({ name, description, parameters }) => ({\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\tparameters,\n\t\t\t\t})),\n\t\t\t},\n\t\t};\n\t\tlines.push(JSON.stringify(shareEntry));\n\t}\n\n\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\treturn filePath;\n}\n\n// =========================================================================\n// Utilities\n// =========================================================================\n\n/**\n * Get text content of last assistant message.\n * Useful for /copy command.\n * @returns Text content, or undefined if no assistant message exists\n */\n\nexport function getLastAssistantText(this: AgentSession): string | undefined {\n\tfor (const message of this.messages.slice().reverse()) {\n\t\tif (message.role !== \"assistant\") continue;\n\t\tconst assistant = message as AssistantMessage;\n\t\t// Skip aborted messages with no content\n\t\tif (assistant.stopReason === \"aborted\" && assistant.content.length === 0) continue;\n\t\tlet text = \"\";\n\t\tfor (const content of assistant.content) {\n\t\t\tif (content.type === \"text\") text += content.text;\n\t\t}\n\t\tconst trimmed = text.trim();\n\t\tif (trimmed) return trimmed;\n\t}\n\treturn undefined;\n}\n\n// =========================================================================\n// Extension System\n// =========================================================================\n\nexport function createReplacedSessionContext(this: AgentSession): ReplacedSessionContext {\n\tconst context = Object.defineProperties(\n\t\t{},\n\t\tObject.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()),\n\t) as ReplacedSessionContext;\n\tcontext.sendMessage = (message, options) => this.sendCustomMessage(message, options);\n\tcontext.sendUserMessage = (content, options) => this.sendUserMessage(content, options);\n\treturn context;\n}\n\n/**\n * Check if extensions have handlers for a specific event type.\n */\n\nexport function hasExtensionHandlers(this: AgentSession, eventType: string): boolean {\n\treturn this._extensionRunner.hasHandlers(eventType);\n}\n\n/**\n * Get the extension runner (for setting UI context and error handlers).\n */\n\nexport const agentSessionExportMethods = {\n\tgetSessionStats,\n\tgetContextUsage,\n\texportToHtml,\n\texportToJsonl,\n\tgetLastAssistantText,\n\tcreateReplacedSessionContext,\n\thasExtensionHandlers,\n};\n"]}
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* and converting the ANSI output to HTML.
|
|
6
6
|
*/
|
|
7
7
|
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
|
8
|
-
import type {
|
|
8
|
+
import type { ToolRenderers } from "../extensions/types.ts";
|
|
9
9
|
export interface ToolHtmlRendererDeps {
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/** Renderers of calls to a tool, resolved by extensions and the registered tool. */
|
|
11
|
+
getToolRenderers: (name: string) => ToolRenderers | undefined;
|
|
12
12
|
/** Theme for styling */
|
|
13
13
|
theme: Theme;
|
|
14
14
|
/** Working directory for render context */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,oFAAoF;IACpF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC9D,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAkHnF"}
|
|
@@ -25,7 +25,7 @@ function trimRenderedResultLines(lines) {
|
|
|
25
25
|
return lines.slice(start, end);
|
|
26
26
|
}
|
|
27
27
|
export function createToolHtmlRenderer(deps) {
|
|
28
|
-
const {
|
|
28
|
+
const { getToolRenderers, theme, cwd, width = 100 } = deps;
|
|
29
29
|
const renderedCallComponents = new Map();
|
|
30
30
|
const renderedResultComponents = new Map();
|
|
31
31
|
const renderedStates = new Map();
|
|
@@ -58,7 +58,7 @@ export function createToolHtmlRenderer(deps) {
|
|
|
58
58
|
renderCall(toolCallId, toolName, args) {
|
|
59
59
|
try {
|
|
60
60
|
renderedArgs.set(toolCallId, args);
|
|
61
|
-
const toolDef =
|
|
61
|
+
const toolDef = getToolRenderers(toolName);
|
|
62
62
|
if (!toolDef?.renderCall) {
|
|
63
63
|
return undefined;
|
|
64
64
|
}
|
|
@@ -74,7 +74,7 @@ export function createToolHtmlRenderer(deps) {
|
|
|
74
74
|
},
|
|
75
75
|
renderResult(toolCallId, toolName, result, details, isError) {
|
|
76
76
|
try {
|
|
77
|
-
const toolDef =
|
|
77
|
+
const toolDef = getToolRenderers(toolName);
|
|
78
78
|
if (!toolDef?.renderResult) {
|
|
79
79
|
return undefined;
|
|
80
80
|
}
|