@botiverse/raft-daemon 0.69.0 → 0.70.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/dist/{chunk-URPIDKXK.js → chunk-SIGIQH6T.js} +891 -56
- package/dist/cli/index.js +860 -354
- package/dist/core.js +9 -1
- package/dist/{dist-P3SAWND7.js → dist-D77BWHH4.js} +842 -350
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core.ts
|
|
2
|
-
import
|
|
2
|
+
import path20 from "path";
|
|
3
3
|
import os8 from "os";
|
|
4
4
|
import { createRequire as createRequire3 } from "module";
|
|
5
5
|
import { accessSync } from "fs";
|
|
@@ -1105,6 +1105,7 @@ function projectTraceScopeAttrs(scope) {
|
|
|
1105
1105
|
addOptionalStringAttr(attrs, "route_pattern", scope.request?.routePattern);
|
|
1106
1106
|
addOptionalStringAttr(attrs, "method", scope.request?.method);
|
|
1107
1107
|
addOptionalStringAttr(attrs, "caller_kind", scope.request?.callerKind);
|
|
1108
|
+
addOptionalStringAttr(attrs, "user_id", scope.request?.userId);
|
|
1108
1109
|
if (typeof scope.request?.userIdPresent === "boolean") {
|
|
1109
1110
|
attrs.user_id_present = scope.request.userIdPresent;
|
|
1110
1111
|
}
|
|
@@ -1280,10 +1281,24 @@ var RecordingActiveSpan = class {
|
|
|
1280
1281
|
}
|
|
1281
1282
|
addEvent(name, attrs) {
|
|
1282
1283
|
if (this.ended) return;
|
|
1283
|
-
|
|
1284
|
+
const event = {
|
|
1284
1285
|
name,
|
|
1285
1286
|
timeMs: this.clock(),
|
|
1286
1287
|
...attrs ? { attrs } : {}
|
|
1288
|
+
};
|
|
1289
|
+
const eventIndex = this.events.length;
|
|
1290
|
+
this.events.push(event);
|
|
1291
|
+
this.sink.recordEvent?.({
|
|
1292
|
+
span: {
|
|
1293
|
+
context: this.context,
|
|
1294
|
+
name: this.name,
|
|
1295
|
+
surface: this.surface,
|
|
1296
|
+
kind: this.kind,
|
|
1297
|
+
startTimeMs: this.startTimeMs,
|
|
1298
|
+
...this.attrs ? { attrs: this.attrs } : {}
|
|
1299
|
+
},
|
|
1300
|
+
event,
|
|
1301
|
+
eventIndex
|
|
1287
1302
|
});
|
|
1288
1303
|
}
|
|
1289
1304
|
end(status = "ok", options = {}) {
|
|
@@ -1291,7 +1306,7 @@ var RecordingActiveSpan = class {
|
|
|
1291
1306
|
this.ended = true;
|
|
1292
1307
|
const endTimeMs = this.clock();
|
|
1293
1308
|
const attrs = mergeAttrs(this.attrs, options.attrs);
|
|
1294
|
-
|
|
1309
|
+
const completed = {
|
|
1295
1310
|
context: this.context,
|
|
1296
1311
|
name: this.name,
|
|
1297
1312
|
surface: this.surface,
|
|
@@ -1302,7 +1317,9 @@ var RecordingActiveSpan = class {
|
|
|
1302
1317
|
durationMs: Math.max(0, endTimeMs - this.startTimeMs),
|
|
1303
1318
|
...attrs ? { attrs } : {},
|
|
1304
1319
|
events: [...this.events]
|
|
1305
|
-
}
|
|
1320
|
+
};
|
|
1321
|
+
this.sink.recordSpanFact?.({ span: completed });
|
|
1322
|
+
this.sink.record(completed);
|
|
1306
1323
|
}
|
|
1307
1324
|
};
|
|
1308
1325
|
function mergeAttrs(base, extra) {
|
|
@@ -1337,6 +1354,125 @@ function randomHex(length) {
|
|
|
1337
1354
|
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1338
1355
|
}
|
|
1339
1356
|
|
|
1357
|
+
// ../shared/src/tracing/eventRows.ts
|
|
1358
|
+
var PROMOTED_IDENTITY_ATTRS = [
|
|
1359
|
+
"server_id",
|
|
1360
|
+
"machine_id",
|
|
1361
|
+
"agent_id",
|
|
1362
|
+
"launch_id",
|
|
1363
|
+
"session_id",
|
|
1364
|
+
"request_id",
|
|
1365
|
+
"route_pattern",
|
|
1366
|
+
"caller_kind"
|
|
1367
|
+
];
|
|
1368
|
+
var PROMOTED_CLOSED_ATTRS = [
|
|
1369
|
+
"outcome",
|
|
1370
|
+
"reason",
|
|
1371
|
+
"event_kind",
|
|
1372
|
+
"source",
|
|
1373
|
+
"authority",
|
|
1374
|
+
"activity_write_site",
|
|
1375
|
+
"activity_source",
|
|
1376
|
+
"hint_source",
|
|
1377
|
+
"resolved_activity",
|
|
1378
|
+
"previous_activity",
|
|
1379
|
+
"next_activity",
|
|
1380
|
+
"repair_kind",
|
|
1381
|
+
"action",
|
|
1382
|
+
"error_class",
|
|
1383
|
+
"status_bucket",
|
|
1384
|
+
"shadow_agent_id",
|
|
1385
|
+
"shadow_signal_site",
|
|
1386
|
+
"shadow_observation_class",
|
|
1387
|
+
"shadow_prior_projection",
|
|
1388
|
+
"shadow_projection",
|
|
1389
|
+
"shadow_legacy_outcome",
|
|
1390
|
+
"shadow_action",
|
|
1391
|
+
"shadow_reason",
|
|
1392
|
+
"shadow_direction",
|
|
1393
|
+
"shadow_plan_kind"
|
|
1394
|
+
];
|
|
1395
|
+
var TRACE_EVENT_ROW_PROMOTED_ATTRS = [
|
|
1396
|
+
...PROMOTED_IDENTITY_ATTRS,
|
|
1397
|
+
...PROMOTED_CLOSED_ATTRS
|
|
1398
|
+
];
|
|
1399
|
+
|
|
1400
|
+
// ../shared/src/tracing/fields.ts
|
|
1401
|
+
function defineTraceFields(definitions) {
|
|
1402
|
+
for (const definition of definitions) {
|
|
1403
|
+
if (definition.fieldClass === "content_safety" && !definition.contentRule) {
|
|
1404
|
+
throw new Error(`Trace content-safety field "${definition.key}" must define a contentRule`);
|
|
1405
|
+
}
|
|
1406
|
+
if ((definition.fieldClass === "query_axis" || definition.fieldClass === "family_query_axis") && definition.valueKind === "content") {
|
|
1407
|
+
throw new Error(`Trace query-axis field "${definition.key}" cannot be content`);
|
|
1408
|
+
}
|
|
1409
|
+
if (definition.fieldClass === "family_query_axis" && !definition.scope) {
|
|
1410
|
+
throw new Error(`Trace family query-axis field "${definition.key}" must define a family scope`);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
return definitions;
|
|
1414
|
+
}
|
|
1415
|
+
var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
|
|
1416
|
+
{ key: "row_kind", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "stable" },
|
|
1417
|
+
{ key: "trace_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1418
|
+
{ key: "span_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1419
|
+
{ key: "parent_span_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1420
|
+
{ key: "span_name", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1421
|
+
{ key: "span_surface", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
|
|
1422
|
+
{ key: "span_kind", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
|
|
1423
|
+
{ key: "span_status", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
|
|
1424
|
+
{ key: "event_name", fieldClass: "query_axis", placement: "event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1425
|
+
{ key: "event_kind", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1426
|
+
{ key: "event_index", fieldClass: "query_axis", placement: "event", valueKind: "identity" },
|
|
1427
|
+
{ key: "event_time", fieldClass: "query_axis", placement: "event", valueKind: "timestamp" },
|
|
1428
|
+
{ key: "event_time_ms", fieldClass: "query_axis", placement: "event", valueKind: "numeric" },
|
|
1429
|
+
{ key: "lifecycle_observed_at_ms", fieldClass: "query_axis", placement: "span_or_event", valueKind: "numeric" },
|
|
1430
|
+
{ key: "activity_observed_at_ms", fieldClass: "query_axis", placement: "span_or_event", valueKind: "numeric" },
|
|
1431
|
+
{ key: "advances_observed_clock", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1432
|
+
{ key: "duration_ms", fieldClass: "query_axis", placement: "span_or_event", valueKind: "numeric" },
|
|
1433
|
+
{ key: "request_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1434
|
+
{ key: "route_pattern", fieldClass: "query_axis", placement: "span", valueKind: "route" },
|
|
1435
|
+
{ key: "caller_kind", fieldClass: "query_axis", placement: "span", valueKind: "closed_enum", enumBinding: "stable" },
|
|
1436
|
+
{ key: "server_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1437
|
+
{ key: "machine_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1438
|
+
{ key: "agent_id", fieldClass: "query_axis", placement: "span_or_event", valueKind: "identity", highCardinality: true },
|
|
1439
|
+
{ key: "launch_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1440
|
+
{ key: "session_id", fieldClass: "query_axis", placement: "span", valueKind: "identity", highCardinality: true },
|
|
1441
|
+
{ key: "observation_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1442
|
+
{ key: "action", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1443
|
+
{ key: "source", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1444
|
+
{ key: "served_from", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1445
|
+
{ key: "authority", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1446
|
+
{ key: "decided_by", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1447
|
+
{ key: "error_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1448
|
+
{ key: "query_name", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "query_registry" },
|
|
1449
|
+
{ key: "phase", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1450
|
+
{ key: "hint_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1451
|
+
{ key: "resolved_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1452
|
+
{ key: "previous_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1453
|
+
{ key: "next_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1454
|
+
{ key: "repair_kind", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1455
|
+
{ key: "activity_write_site", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1456
|
+
{ key: "activity_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1457
|
+
{ key: "status_bucket", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1458
|
+
{ key: "shadow_agent_id", fieldClass: "family_query_axis", placement: "event", valueKind: "identity", scope: "family:lifecycle_shadow", highCardinality: true },
|
|
1459
|
+
{ key: "shadow_signal_site", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1460
|
+
{ key: "shadow_observation_class", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1461
|
+
{ key: "shadow_prior_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1462
|
+
{ key: "shadow_projection", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1463
|
+
{ key: "shadow_legacy_outcome", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1464
|
+
{ key: "shadow_action", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1465
|
+
{ key: "shadow_reason", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1466
|
+
{ key: "shadow_direction", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1467
|
+
{ key: "shadow_plan_kind", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:lifecycle_shadow", enumBinding: "pending_457" },
|
|
1468
|
+
{ key: "row_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
|
|
1469
|
+
{ key: "retry_count", fieldClass: "detail", placement: "span_or_event", valueKind: "detail" },
|
|
1470
|
+
{ key: "error_message", fieldClass: "detail", placement: "span_or_event", valueKind: "detail", contentRule: "scrub_and_short_retention" },
|
|
1471
|
+
{ key: "query_text", fieldClass: "content_safety", placement: "span_or_event", valueKind: "content", contentRule: "scrub_and_short_retention" },
|
|
1472
|
+
{ key: "raw_payload", fieldClass: "content_safety", placement: "span_or_event", valueKind: "content", contentRule: "drop" },
|
|
1473
|
+
{ key: "token", fieldClass: "content_safety", placement: "span_or_event", valueKind: "content", contentRule: "drop" }
|
|
1474
|
+
]);
|
|
1475
|
+
|
|
1340
1476
|
// ../shared/src/toolDisplay.ts
|
|
1341
1477
|
var TOOL_DISPLAY_METADATA = {
|
|
1342
1478
|
send_message: { logLabel: "Sending message", activityLabel: "Sending message\u2026", summaryKind: "message_target" },
|
|
@@ -1986,7 +2122,8 @@ var agentApiResolveChannelResponseSchema = passthroughObject({
|
|
|
1986
2122
|
channelId: z2.string().trim().min(1)
|
|
1987
2123
|
});
|
|
1988
2124
|
var agentApiThreadUnfollowBodySchema = passthroughObject({
|
|
1989
|
-
thread: z2.string().trim().min(1)
|
|
2125
|
+
thread: z2.string().trim().min(1),
|
|
2126
|
+
reason: z2.string().trim().min(1).max(200).optional()
|
|
1990
2127
|
});
|
|
1991
2128
|
var agentApiTaskClaimBodySchema = passthroughObject({
|
|
1992
2129
|
channel: z2.string().trim().min(1),
|
|
@@ -2225,7 +2362,12 @@ var agentApiIntegrationLoginResponseSchema = passthroughObject({
|
|
|
2225
2362
|
status: z2.enum(["logged_in", "already_logged_in", "approval_required"]),
|
|
2226
2363
|
service: agentApiIntegrationServiceSchema,
|
|
2227
2364
|
scopes: z2.array(z2.string()),
|
|
2228
|
-
requestId: z2.string(),
|
|
2365
|
+
requestId: z2.string().optional(),
|
|
2366
|
+
session: passthroughObject({
|
|
2367
|
+
status: z2.literal("stored"),
|
|
2368
|
+
source: z2.enum(["cache", "fresh"]),
|
|
2369
|
+
path: nullableStringSchema
|
|
2370
|
+
}).optional(),
|
|
2229
2371
|
approval: passthroughObject({
|
|
2230
2372
|
requestId: z2.string(),
|
|
2231
2373
|
target: nullableStringSchema,
|
|
@@ -3182,6 +3324,55 @@ var SUPPORTED_TRANSLATION_LANGUAGE_SET = new Set(
|
|
|
3182
3324
|
SUPPORTED_TRANSLATION_LANGUAGE_CODES
|
|
3183
3325
|
);
|
|
3184
3326
|
|
|
3327
|
+
// ../shared/src/oauthScopes.ts
|
|
3328
|
+
var RAFT_OAUTH_SCOPE_CATALOG = {
|
|
3329
|
+
openid: {
|
|
3330
|
+
phase: "identity",
|
|
3331
|
+
defaultAllowed: true,
|
|
3332
|
+
publicDiscovery: true,
|
|
3333
|
+
requiresResource: false,
|
|
3334
|
+
label: "OpenID identity"
|
|
3335
|
+
},
|
|
3336
|
+
profile: {
|
|
3337
|
+
phase: "identity",
|
|
3338
|
+
defaultAllowed: true,
|
|
3339
|
+
publicDiscovery: true,
|
|
3340
|
+
requiresResource: false,
|
|
3341
|
+
label: "Basic profile"
|
|
3342
|
+
},
|
|
3343
|
+
identity: {
|
|
3344
|
+
phase: "identity",
|
|
3345
|
+
defaultAllowed: true,
|
|
3346
|
+
publicDiscovery: true,
|
|
3347
|
+
requiresResource: false,
|
|
3348
|
+
label: "Raft identity card"
|
|
3349
|
+
},
|
|
3350
|
+
"agent:event:write": {
|
|
3351
|
+
phase: "agent_inbound",
|
|
3352
|
+
defaultAllowed: false,
|
|
3353
|
+
publicDiscovery: true,
|
|
3354
|
+
requiresResource: true,
|
|
3355
|
+
label: "Send structured events to an agent"
|
|
3356
|
+
},
|
|
3357
|
+
"agent:notification:write": {
|
|
3358
|
+
phase: "agent_inbound",
|
|
3359
|
+
defaultAllowed: false,
|
|
3360
|
+
publicDiscovery: true,
|
|
3361
|
+
requiresResource: true,
|
|
3362
|
+
label: "Send notifications to an agent"
|
|
3363
|
+
},
|
|
3364
|
+
"agent:action_request:write": {
|
|
3365
|
+
phase: "agent_inbound",
|
|
3366
|
+
defaultAllowed: false,
|
|
3367
|
+
publicDiscovery: false,
|
|
3368
|
+
requiresResource: true,
|
|
3369
|
+
label: "Request agent action"
|
|
3370
|
+
}
|
|
3371
|
+
};
|
|
3372
|
+
var RAFT_OAUTH_SCOPES_SUPPORTED = Object.keys(RAFT_OAUTH_SCOPE_CATALOG);
|
|
3373
|
+
var RAFT_OAUTH_DEFAULT_ALLOWED_SCOPES = RAFT_OAUTH_SCOPES_SUPPORTED.filter((scope) => RAFT_OAUTH_SCOPE_CATALOG[scope].defaultAllowed);
|
|
3374
|
+
var RAFT_OAUTH_PUBLIC_DISCOVERY_SCOPES = RAFT_OAUTH_SCOPES_SUPPORTED.filter((scope) => RAFT_OAUTH_SCOPE_CATALOG[scope].publicDiscovery);
|
|
3375
|
+
|
|
3185
3376
|
// ../shared/src/testing/failpoints.ts
|
|
3186
3377
|
var NoopFailpointRegistry = class {
|
|
3187
3378
|
get enabled() {
|
|
@@ -3739,6 +3930,8 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
3739
3930
|
}
|
|
3740
3931
|
};
|
|
3741
3932
|
var FREE_MONTHLY_FILE_UPLOAD_LIMIT_BYTES = 100 * 1024 * 1024;
|
|
3933
|
+
var FREE_SINGLE_FILE_UPLOAD_LIMIT_BYTES = 50 * 1024 * 1024;
|
|
3934
|
+
var PRO_SINGLE_FILE_UPLOAD_LIMIT_BYTES = 200 * 1024 * 1024;
|
|
3742
3935
|
var TRIAL_START_DATE = /* @__PURE__ */ new Date("2026-04-18T00:00:00Z");
|
|
3743
3936
|
var TRIAL_END_DATE = /* @__PURE__ */ new Date("2026-06-23T12:00:00Z");
|
|
3744
3937
|
var TRIAL_DURATION_DAYS = (TRIAL_END_DATE.getTime() - TRIAL_START_DATE.getTime()) / (24 * 60 * 60 * 1e3);
|
|
@@ -4018,8 +4211,8 @@ async function executeResponseRequest(url, init, {
|
|
|
4018
4211
|
}
|
|
4019
4212
|
|
|
4020
4213
|
// src/directUploadCapability.ts
|
|
4021
|
-
function joinUrl(base,
|
|
4022
|
-
return `${base.replace(/\/+$/, "")}${
|
|
4214
|
+
function joinUrl(base, path21) {
|
|
4215
|
+
return `${base.replace(/\/+$/, "")}${path21}`;
|
|
4023
4216
|
}
|
|
4024
4217
|
function jsonHeaders(apiKey) {
|
|
4025
4218
|
return {
|
|
@@ -4237,7 +4430,7 @@ Threads are sub-conversations attached to a specific message. They let you discu
|
|
|
4237
4430
|
- When you receive a message from a thread (the target has a \`:shortid\` suffix), **always reply using that same target** to keep the conversation in the thread.
|
|
4238
4431
|
- **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=00000000 ...]\`, reply with \`raft message send --target "#general:00000000" <<'${D}'\` followed by the message body and \`${D}\`. The thread will be auto-created if it doesn't exist yet. Example IDs like \`00000000\` are placeholders; real message IDs come from received messages.
|
|
4239
4432
|
- When you send a message, the response includes the message ID. You can use it to start a thread on your own message.
|
|
4240
|
-
- You can read thread history: \`raft message read --
|
|
4433
|
+
- You can read thread history: \`raft message read --target "#general:00000000"\`
|
|
4241
4434
|
- You can stop receiving ordinary delivery for a thread with \`raft thread unfollow --target "#general:00000000"\`. Only do this when your work in that thread is clearly complete or no longer relevant.
|
|
4242
4435
|
- Threads cannot be nested \u2014 you cannot start a thread inside a thread.`;
|
|
4243
4436
|
}
|
|
@@ -4245,7 +4438,7 @@ function buildDiscoverySection() {
|
|
|
4245
4438
|
return `### Discovering people and channels
|
|
4246
4439
|
|
|
4247
4440
|
Call \`raft server info\` to see all channels in this server, which ones you have joined, other agents, and humans.
|
|
4248
|
-
Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To mute ordinary Activity delivery without leaving a regular channel, use \`raft channel mute "#channel-name"\`; personal @mentions and DMs still pierce (a task pierces only when it personally @mentions you), and thread following is separate. To reverse that setting, use \`raft channel unmute "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
|
|
4441
|
+
Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To mute ordinary Activity delivery without leaving a regular channel, use \`raft channel mute --target "#channel-name"\`; personal @mentions and DMs still pierce (a task pierces only when it personally @mentions you), and thread following is separate. To reverse that setting, use \`raft channel unmute --target "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
|
|
4249
4442
|
Private channels are membership-gated. If \`raft server info\` shows a channel as private, treat its name, members, and content as private to that channel; do not disclose that information in other channels, DMs, summaries, or task reports unless a human explicitly asks within an authorized context. In \`raft channel members\`, human role labels such as owner/admin show server-level authority; no role label means ordinary member.`;
|
|
4250
4443
|
}
|
|
4251
4444
|
function buildChannelAwarenessSection() {
|
|
@@ -4259,9 +4452,9 @@ Each channel has a **name** and optionally a **description** that define its pur
|
|
|
4259
4452
|
function buildReadingHistorySection() {
|
|
4260
4453
|
return `### Reading history
|
|
4261
4454
|
|
|
4262
|
-
\`raft message read --
|
|
4455
|
+
\`raft message read --target "#channel-name"\` or \`raft message read --target dm:@peer-name\` or \`raft message read --target "#channel:shortid"\`
|
|
4263
4456
|
|
|
4264
|
-
To jump directly to a specific hit with nearby context, use \`raft message read --
|
|
4457
|
+
To jump directly to a specific hit with nearby context, use \`raft message read --target "..." --around "messageId"\` or \`raft message read --target "..." --around 12345\`.`;
|
|
4265
4458
|
}
|
|
4266
4459
|
function buildHistoricalReferencesSection() {
|
|
4267
4460
|
return `### Historical references
|
|
@@ -4290,7 +4483,7 @@ Only top-level channel / DM messages can become tasks. Messages inside threads a
|
|
|
4290
4483
|
**Assignee** is independent from status \u2014 a task can be claimed or unclaimed at any status except \`done\`.
|
|
4291
4484
|
|
|
4292
4485
|
**Workflow:**
|
|
4293
|
-
1. Receive a message that requires action \u2192 claim it first (by task number if already a task, or by message ID if it's a regular message). Use repeat flags: \`raft task claim --
|
|
4486
|
+
1. Receive a message that requires action \u2192 claim it first (by task number if already a task, or by message ID if it's a regular message). Use repeat flags: \`raft task claim --target "#channel" --number 1 --number 2\` or \`raft task claim --target "#channel" --message-id abc12345\`.
|
|
4294
4487
|
2. If the claim fails, someone else is working on it \u2014 do not work on that task unless an owner/admin explicitly redirects it to you
|
|
4295
4488
|
3. Post updates in the task's thread: \`raft message send --target "#channel:msgShortId" <<'${D}'\` followed by the message body and \`${D}\`
|
|
4296
4489
|
4. When done, set status to \`in_review\` so a human can validate via \`raft task update\`
|
|
@@ -4302,7 +4495,7 @@ Only top-level channel / DM messages can become tasks. Messages inside threads a
|
|
|
4302
4495
|
- \`raft task create\` only creates the task \u2014 to own it, call \`raft task claim\` afterward.
|
|
4303
4496
|
- Typical uses for \`raft task create\` are breaking down a larger task into parallel subtasks, or batch-creating genuinely new work for others to claim.
|
|
4304
4497
|
- If someone already sent the work item as a message, just claim that existing message/task instead of creating a new one.
|
|
4305
|
-
- If the work already exists as a message, reuse it via \`raft task claim --
|
|
4498
|
+
- If the work already exists as a message, reuse it via \`raft task claim --target "#channel" --message-id abc12345\`.
|
|
4306
4499
|
|
|
4307
4500
|
**Creating new tasks:**
|
|
4308
4501
|
- The task system exists to prevent duplicate work. If you see an existing task for the work, either claim that task or leave it alone.
|
|
@@ -4521,7 +4714,7 @@ function buildPrompt(config, opts) {
|
|
|
4521
4714
|
const channelAwarenessSection = cliGuideSections.channelAwareness;
|
|
4522
4715
|
const thirdPartyIntegrationsSection = `### Third-party integrations
|
|
4523
4716
|
|
|
4524
|
-
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes manifest-backed HTTP API actions, prefer \`raft integration invoke --service <service> --list-actions\` and then \`raft integration invoke --service <service> --action <name>\`; the CLI
|
|
4717
|
+
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service; the CLI consumes the one-time Agent Login handoff internally and stores the service-owned session for this agent, so the successful output should be \`Agent login ready\` / \`Already logged in\`, not a raw request code you need to keep. If the service exposes manifest-backed HTTP API actions, prefer \`raft integration invoke --service <service> --list-actions\` and then \`raft integration invoke --service <service> --action <name>\`; the CLI uses the stored service session or refreshes it internally. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`raft integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides; for HTTP API action services, use \`raft integration invoke\` instead. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute local commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. Do not store or reuse raw \`oauth_access_request\` request codes; those are one-time compatibility handoffs for services to exchange once for their own session/token. Prefer \`raft integration invoke\` over manually opening or curling callback URLs. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes outside the documented CLI flow, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`raft profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
|
|
4525
4718
|
const readingHistorySection = cliGuideSections.readingHistory;
|
|
4526
4719
|
const historicalReferenceSection = cliGuideSections.historicalReferences;
|
|
4527
4720
|
const tasksSection = cliGuideSections.tasks;
|
|
@@ -5652,7 +5845,7 @@ function shortMessageId2(value) {
|
|
|
5652
5845
|
return value.slice(0, 8);
|
|
5653
5846
|
}
|
|
5654
5847
|
function normalizeSenderType(value) {
|
|
5655
|
-
return value === "human" || value === "agent" || value === "system" ? value : void 0;
|
|
5848
|
+
return value === "human" || value === "agent" || value === "system" || value === "third_party_app" ? value : void 0;
|
|
5656
5849
|
}
|
|
5657
5850
|
function nonEmptyString(value) {
|
|
5658
5851
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
@@ -6040,6 +6233,10 @@ async function readRequestBody(req) {
|
|
|
6040
6233
|
function messageSeq3(message) {
|
|
6041
6234
|
return Number(message.seq ?? 0);
|
|
6042
6235
|
}
|
|
6236
|
+
function isThirdPartyAgentEvent(message) {
|
|
6237
|
+
const thirdPartyEvent = message.third_party_event;
|
|
6238
|
+
return typeof thirdPartyEvent?.id === "string" && thirdPartyEvent.id.length > 0;
|
|
6239
|
+
}
|
|
6043
6240
|
function localAgentApiInboxResponse(registration) {
|
|
6044
6241
|
const coordinator = registration.inboxCoordinator;
|
|
6045
6242
|
if (!coordinator) return void 0;
|
|
@@ -6090,6 +6287,7 @@ function localAgentApiEventsResponse(registration, target) {
|
|
|
6090
6287
|
const normalized = sortInboxMessagesBySeq(normalizeInboxVisibleMessages(pending));
|
|
6091
6288
|
const filtered = parsedQuery.sinceSeq !== null ? normalized.filter((message) => {
|
|
6092
6289
|
const seq = messageSeq3(message);
|
|
6290
|
+
if ((!Number.isFinite(seq) || seq <= 0) && isThirdPartyAgentEvent(message)) return true;
|
|
6093
6291
|
return Number.isFinite(seq) && seq > parsedQuery.sinceSeq;
|
|
6094
6292
|
}) : normalized;
|
|
6095
6293
|
const events = filtered.slice(0, parsedQuery.limit);
|
|
@@ -7658,7 +7856,7 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
7658
7856
|
return null;
|
|
7659
7857
|
}
|
|
7660
7858
|
const sessionId = codexMessageThreadId(message);
|
|
7661
|
-
const
|
|
7859
|
+
const path21 = boundedString(params.path);
|
|
7662
7860
|
return {
|
|
7663
7861
|
kind: "runtime_diagnostic",
|
|
7664
7862
|
severity: "warning",
|
|
@@ -7666,7 +7864,7 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
7666
7864
|
itemType: message.method,
|
|
7667
7865
|
message: diagnosticMessage,
|
|
7668
7866
|
...details ? { details } : {},
|
|
7669
|
-
...
|
|
7867
|
+
...path21 ? { path: path21 } : {},
|
|
7670
7868
|
...params.range !== void 0 ? { range: params.range } : {},
|
|
7671
7869
|
payloadBytes: payloadBytes(params),
|
|
7672
7870
|
...sessionId ? { sessionId } : {}
|
|
@@ -12524,6 +12722,9 @@ function computeTarget(channelType, channelName, parentChannelName, parentChanne
|
|
|
12524
12722
|
return `#${channelName}`;
|
|
12525
12723
|
}
|
|
12526
12724
|
function formatAgentMessageVisibleTarget(message) {
|
|
12725
|
+
if (message.third_party_event) {
|
|
12726
|
+
return `agent-event:${getMessageShortId(message.third_party_event.id)}`;
|
|
12727
|
+
}
|
|
12527
12728
|
return computeTarget(message.channel_type, message.channel_name, message.parent_channel_name, message.parent_channel_type);
|
|
12528
12729
|
}
|
|
12529
12730
|
function formatProxyVisibleMessageTarget(message) {
|
|
@@ -13371,24 +13572,38 @@ function safeSessionFilename(value) {
|
|
|
13371
13572
|
const normalized = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13372
13573
|
return normalized || "unknown-session";
|
|
13373
13574
|
}
|
|
13374
|
-
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
13575
|
+
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir, join, resolve) {
|
|
13375
13576
|
try {
|
|
13376
13577
|
const dir = path14.join(fallbackDir, ".slock", "runtime-sessions");
|
|
13377
13578
|
mkdirSync4(dir, { recursive: true });
|
|
13378
13579
|
const filePath = path14.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
|
|
13580
|
+
const searchedPaths = resolve?.searchedPaths ?? [];
|
|
13379
13581
|
writeFileSync4(filePath, JSON.stringify({
|
|
13380
13582
|
type: "runtime_session_handoff",
|
|
13381
13583
|
runtime,
|
|
13382
13584
|
sessionId,
|
|
13585
|
+
// Persisted L1<->L2 join keys (#460 V3): without these the
|
|
13586
|
+
// session->launch mapping lives only in daemon memory and old L1
|
|
13587
|
+
// transcripts can never re-join their launch after restart/adopt.
|
|
13588
|
+
// ids-only, closed fields (no content payload).
|
|
13589
|
+
launchId: join?.launchId ?? null,
|
|
13590
|
+
processInstanceId: join?.processInstanceId ?? null,
|
|
13591
|
+
// Negative-space (fruit#0 pt2): a resolve-miss is explicit evidence, not a
|
|
13592
|
+
// silent "not found". Recording the lookup method + the directories checked
|
|
13593
|
+
// makes "looked in the wrong place" distinguishable from "looked in the right
|
|
13594
|
+
// place and it is genuinely absent". ids/paths only — no transcript content.
|
|
13595
|
+
resolveStatus: "transcript_resolve_missing",
|
|
13596
|
+
lookupMethod: resolve?.lookupMethod ?? "none",
|
|
13597
|
+
searchedPaths,
|
|
13383
13598
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13384
|
-
note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the runtime session identity for diagnostics."
|
|
13599
|
+
note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the runtime session identity + the directories checked for diagnostics."
|
|
13385
13600
|
}) + "\n", { mode: 384 });
|
|
13386
13601
|
return {
|
|
13387
13602
|
label: sessionId,
|
|
13388
13603
|
path: filePath,
|
|
13389
13604
|
runtime,
|
|
13390
13605
|
reachable: true,
|
|
13391
|
-
reason:
|
|
13606
|
+
reason: `native session file path not found; using daemon handoff file; searched=[${searchedPaths.join(", ")}]`
|
|
13392
13607
|
};
|
|
13393
13608
|
} catch {
|
|
13394
13609
|
return null;
|
|
@@ -13413,12 +13628,16 @@ function ensureRuntimeHomeDir(config, defaultHomeDir, workspacePath, opts = {})
|
|
|
13413
13628
|
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), fallbackDir, opts) {
|
|
13414
13629
|
let resolvedPath = null;
|
|
13415
13630
|
let lookupMethod = "none";
|
|
13631
|
+
const searchedPaths = [];
|
|
13416
13632
|
if (runtime === "claude") {
|
|
13417
13633
|
lookupMethod = "claude_jsonl";
|
|
13418
|
-
|
|
13634
|
+
const claudeRoot = path14.join(homeDir, ".claude", "projects");
|
|
13635
|
+
searchedPaths.push(claudeRoot);
|
|
13636
|
+
resolvedPath = findSessionJsonl(claudeRoot, (filename) => filename === `${sessionId}.jsonl`);
|
|
13419
13637
|
} else if (runtime === "codex") {
|
|
13420
13638
|
lookupMethod = "codex_jsonl";
|
|
13421
13639
|
for (const root of codexSessionRootCandidates(homeDir)) {
|
|
13640
|
+
searchedPaths.push(root);
|
|
13422
13641
|
resolvedPath = findSessionJsonl(root, (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId));
|
|
13423
13642
|
if (resolvedPath) break;
|
|
13424
13643
|
}
|
|
@@ -13430,7 +13649,13 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
|
|
|
13430
13649
|
resolvedPath = findPiSessionFile2(sessionId, opts?.workingDirectory, homeDir);
|
|
13431
13650
|
}
|
|
13432
13651
|
if (!resolvedPath && fallbackDir) {
|
|
13433
|
-
const fallback = writeRuntimeSessionHandoff(
|
|
13652
|
+
const fallback = writeRuntimeSessionHandoff(
|
|
13653
|
+
runtime,
|
|
13654
|
+
sessionId,
|
|
13655
|
+
fallbackDir,
|
|
13656
|
+
{ launchId: opts?.launchId, processInstanceId: opts?.processInstanceId },
|
|
13657
|
+
{ lookupMethod, searchedPaths }
|
|
13658
|
+
);
|
|
13434
13659
|
if (fallback) {
|
|
13435
13660
|
return {
|
|
13436
13661
|
...fallback,
|
|
@@ -13445,7 +13670,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
|
|
|
13445
13670
|
reachable: Boolean(resolvedPath)
|
|
13446
13671
|
};
|
|
13447
13672
|
if (!resolvedPath) {
|
|
13448
|
-
ref.reason = `session file path not found; attempted_lookup=${lookupMethod}`;
|
|
13673
|
+
ref.reason = `session file path not found; attempted_lookup=${lookupMethod}; searched=[${searchedPaths.join(", ")}]`;
|
|
13449
13674
|
}
|
|
13450
13675
|
return ref;
|
|
13451
13676
|
}
|
|
@@ -13499,7 +13724,7 @@ function formatIncomingMessage(message, options = {}) {
|
|
|
13499
13724
|
`[Slock thread context: you were added to a new thread via @mention.]`,
|
|
13500
13725
|
`parent: ${message.thread_join_context.parent_target}`,
|
|
13501
13726
|
`thread: ${message.thread_join_context.thread_target}`,
|
|
13502
|
-
`suggested next step: raft message read --
|
|
13727
|
+
`suggested next step: raft message read --target "${message.thread_join_context.suggested_read_history_target}"`,
|
|
13503
13728
|
"",
|
|
13504
13729
|
"Parent message:",
|
|
13505
13730
|
formatThreadContextMessage(message.thread_join_context.parent_message),
|
|
@@ -15329,7 +15554,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15329
15554
|
detailKind: activity.statusEntry.detailKind ?? "daemon_activity",
|
|
15330
15555
|
entries: activity.entries,
|
|
15331
15556
|
launchId: ap?.launchId || void 0,
|
|
15332
|
-
clientSeq: ap ? this.nextActivityClientSeq(agentId) : void 0
|
|
15557
|
+
clientSeq: ap ? this.nextActivityClientSeq(agentId) : void 0,
|
|
15558
|
+
isHeartbeat: false
|
|
15333
15559
|
});
|
|
15334
15560
|
}
|
|
15335
15561
|
recordRuntimeDiagnosticActivity(agentId, ap, event) {
|
|
@@ -15342,7 +15568,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15342
15568
|
detailKind: ap.lastActivityDetailKind || "none",
|
|
15343
15569
|
entries: [runtimeDiagnosticTrajectoryEntry(event)],
|
|
15344
15570
|
launchId: ap.launchId || void 0,
|
|
15345
|
-
clientSeq: this.nextActivityClientSeq(agentId)
|
|
15571
|
+
clientSeq: this.nextActivityClientSeq(agentId),
|
|
15572
|
+
isHeartbeat: false
|
|
15346
15573
|
});
|
|
15347
15574
|
this.recordDaemonTrace("daemon.runtime.diagnostic", {
|
|
15348
15575
|
agentId,
|
|
@@ -15393,7 +15620,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15393
15620
|
detailKind: ap.lastActivityDetailKind || "none",
|
|
15394
15621
|
entries: [runtimeRecoveryTrajectoryEntry(event)],
|
|
15395
15622
|
launchId: ap.launchId || void 0,
|
|
15396
|
-
clientSeq: this.nextActivityClientSeq(agentId)
|
|
15623
|
+
clientSeq: this.nextActivityClientSeq(agentId),
|
|
15624
|
+
isHeartbeat: false
|
|
15397
15625
|
});
|
|
15398
15626
|
this.recordDaemonTrace("daemon.runtime.recovery.visible", {
|
|
15399
15627
|
agentId,
|
|
@@ -15641,7 +15869,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15641
15869
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
15642
15870
|
config: this.buildRestartSafeConfig(ap.config, nextConfigSessionId),
|
|
15643
15871
|
sessionId: nextConfigSessionId,
|
|
15644
|
-
launchId: nextLaunchId
|
|
15872
|
+
launchId: nextLaunchId,
|
|
15873
|
+
processInstanceId: ap.processInstanceId
|
|
15645
15874
|
});
|
|
15646
15875
|
this.recordStartRebind(agentId, start, reason, previousLaunchId, nextLaunchId, nextSessionId);
|
|
15647
15876
|
this.sendAgentStatus(agentId, "active", nextLaunchId);
|
|
@@ -16072,6 +16301,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16072
16301
|
config: this.buildRestartSafeConfig(runtimeConfig, runtimeConfig.sessionId || null),
|
|
16073
16302
|
sessionId: runtimeConfig.sessionId || null,
|
|
16074
16303
|
launchId: effectiveLaunchId
|
|
16304
|
+
// No live AgentProcess in this adoption branch — omit rather than
|
|
16305
|
+
// fabricate; the marker's processInstanceId is nullable by contract.
|
|
16075
16306
|
});
|
|
16076
16307
|
this.sendAgentStatus(agentId, "active", effectiveLaunchId);
|
|
16077
16308
|
this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
|
|
@@ -16161,7 +16392,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16161
16392
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16162
16393
|
config: this.buildRestartSafeConfig(runtimeConfig, restartSessionId),
|
|
16163
16394
|
sessionId: restartSessionId,
|
|
16164
|
-
launchId: effectiveLaunchId
|
|
16395
|
+
launchId: effectiveLaunchId,
|
|
16396
|
+
processInstanceId: agentProcess.processInstanceId
|
|
16165
16397
|
});
|
|
16166
16398
|
if (pendingStartRebind) {
|
|
16167
16399
|
this.recordStartRebind(agentId, pendingStartRebind, "startup_registered", originalLaunchId, effectiveLaunchId, agentProcess.sessionId);
|
|
@@ -16363,7 +16595,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16363
16595
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16364
16596
|
config: nextConfig,
|
|
16365
16597
|
sessionId: ap.sessionId,
|
|
16366
|
-
launchId: ap.launchId
|
|
16598
|
+
launchId: ap.launchId,
|
|
16599
|
+
processInstanceId: ap.processInstanceId
|
|
16367
16600
|
});
|
|
16368
16601
|
this.broadcastMessageReceivedActivity(agentId);
|
|
16369
16602
|
this.lifecycleRecords.deleteRestartSnapshot(agentId);
|
|
@@ -16381,7 +16614,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16381
16614
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16382
16615
|
config: nextConfig,
|
|
16383
16616
|
sessionId: ap.sessionId,
|
|
16384
|
-
launchId: ap.launchId
|
|
16617
|
+
launchId: ap.launchId,
|
|
16618
|
+
processInstanceId: ap.processInstanceId
|
|
16385
16619
|
});
|
|
16386
16620
|
const report = this.recordSpawnFailure(agentId, "runner_credential_mint");
|
|
16387
16621
|
this.assertStartPendingDeliveryInvariants("queued-continuation-runner-credential-mint-failure");
|
|
@@ -16401,7 +16635,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16401
16635
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16402
16636
|
config: nextConfig,
|
|
16403
16637
|
sessionId: ap.sessionId,
|
|
16404
|
-
launchId: ap.launchId
|
|
16638
|
+
launchId: ap.launchId,
|
|
16639
|
+
processInstanceId: ap.processInstanceId
|
|
16405
16640
|
});
|
|
16406
16641
|
this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
|
|
16407
16642
|
});
|
|
@@ -16410,7 +16645,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16410
16645
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16411
16646
|
config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
|
|
16412
16647
|
sessionId: ap.sessionId,
|
|
16413
|
-
launchId: ap.launchId
|
|
16648
|
+
launchId: ap.launchId,
|
|
16649
|
+
processInstanceId: ap.processInstanceId
|
|
16414
16650
|
});
|
|
16415
16651
|
if (!ap.driver.supportsStdinNotification) {
|
|
16416
16652
|
logger.info(`[Agent ${agentId}] Turn completed; cached idle state for future restart`);
|
|
@@ -16422,7 +16658,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16422
16658
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16423
16659
|
config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
|
|
16424
16660
|
sessionId: ap.sessionId,
|
|
16425
|
-
launchId: ap.launchId
|
|
16661
|
+
launchId: ap.launchId,
|
|
16662
|
+
processInstanceId: ap.processInstanceId
|
|
16426
16663
|
});
|
|
16427
16664
|
logger.warn(`[Agent ${agentId}] Recoverable provider stream failure (${reason}) \u2014 keeping agent wakeable`);
|
|
16428
16665
|
this.sendAgentStatus(agentId, "active", ap.launchId);
|
|
@@ -16638,7 +16875,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16638
16875
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16639
16876
|
config: retryConfig,
|
|
16640
16877
|
sessionId: retrySessionId,
|
|
16641
|
-
launchId: ap.launchId
|
|
16878
|
+
launchId: ap.launchId,
|
|
16879
|
+
processInstanceId: ap.processInstanceId
|
|
16642
16880
|
});
|
|
16643
16881
|
this.recordDaemonTrace("daemon.agent.startup_timeout.retry_config_cached", {
|
|
16644
16882
|
agentId,
|
|
@@ -17552,7 +17790,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17552
17790
|
}
|
|
17553
17791
|
return result;
|
|
17554
17792
|
}
|
|
17555
|
-
buildRuntimeProfileReport(agentId, config, sessionId, launchId, observedRuntimeHomeDir) {
|
|
17793
|
+
buildRuntimeProfileReport(agentId, config, sessionId, launchId, observedRuntimeHomeDir, processInstanceId) {
|
|
17556
17794
|
const workspacePath = path14.join(this.dataDir, agentId);
|
|
17557
17795
|
const runtimeHomeDir = observedRuntimeHomeDir || resolveRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspacePath, { agentId, slockHome: this.slockHome });
|
|
17558
17796
|
return {
|
|
@@ -17568,7 +17806,16 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17568
17806
|
path: workspacePath,
|
|
17569
17807
|
reachable: true
|
|
17570
17808
|
},
|
|
17571
|
-
sessionRef: sessionId ? resolveRuntimeSessionRef(config.runtime, sessionId, runtimeHomeDir, workspacePath, {
|
|
17809
|
+
sessionRef: sessionId ? resolveRuntimeSessionRef(config.runtime, sessionId, runtimeHomeDir, workspacePath, {
|
|
17810
|
+
agentId,
|
|
17811
|
+
workingDirectory: workspacePath,
|
|
17812
|
+
// Join keys come from the CALLER's context (running agent OR idle
|
|
17813
|
+
// restart snapshot) — reading only live state here left the
|
|
17814
|
+
// restart/adopt path writing launchId:null markers, exactly the
|
|
17815
|
+
// V3 class this exists to close (Leiysky review on #3863).
|
|
17816
|
+
launchId: launchId || void 0,
|
|
17817
|
+
processInstanceId: processInstanceId ?? this.agents.get(agentId)?.processInstanceId
|
|
17818
|
+
}) : null
|
|
17572
17819
|
}
|
|
17573
17820
|
};
|
|
17574
17821
|
}
|
|
@@ -17580,12 +17827,13 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17580
17827
|
running.config,
|
|
17581
17828
|
running.sessionId,
|
|
17582
17829
|
running.launchId,
|
|
17583
|
-
running.runtime.currentRuntimeHomeDir
|
|
17830
|
+
running.runtime.currentRuntimeHomeDir,
|
|
17831
|
+
running.processInstanceId
|
|
17584
17832
|
);
|
|
17585
17833
|
}
|
|
17586
17834
|
const idle = this.lifecycleRecords.getRestartSnapshot(agentId);
|
|
17587
17835
|
if (idle) {
|
|
17588
|
-
return this.buildRuntimeProfileReport(agentId, idle.config, idle.sessionId, idle.launchId);
|
|
17836
|
+
return this.buildRuntimeProfileReport(agentId, idle.config, idle.sessionId, idle.launchId, null, idle.processInstanceId);
|
|
17589
17837
|
}
|
|
17590
17838
|
return null;
|
|
17591
17839
|
}
|
|
@@ -17983,7 +18231,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17983
18231
|
}
|
|
17984
18232
|
const ref = resolveRuntimeSessionRef(runtime, actualSessionId, homeDir, workspaceDir, {
|
|
17985
18233
|
agentId,
|
|
17986
|
-
workingDirectory: workspaceDir
|
|
18234
|
+
workingDirectory: workspaceDir,
|
|
18235
|
+
launchId: this.agents.get(agentId)?.launchId || void 0,
|
|
18236
|
+
processInstanceId: this.agents.get(agentId)?.processInstanceId
|
|
17987
18237
|
});
|
|
17988
18238
|
const tier = runtimeTier(runtime);
|
|
17989
18239
|
const span = this.tracer.startSpan("daemon.session_transcript.read", {
|
|
@@ -18241,6 +18491,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18241
18491
|
const launchId = launchIdOverride || ap?.launchId || void 0;
|
|
18242
18492
|
const clientSeq = this.nextActivityClientSeq(agentId);
|
|
18243
18493
|
const producerFactId = this.buildActivityProducerFactId(agentId, launchId, clientSeq);
|
|
18494
|
+
const observedAtMs = Date.now();
|
|
18244
18495
|
this.sendToServer({
|
|
18245
18496
|
type: "agent:activity",
|
|
18246
18497
|
agentId,
|
|
@@ -18251,9 +18502,11 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18251
18502
|
entries,
|
|
18252
18503
|
launchId,
|
|
18253
18504
|
clientSeq,
|
|
18254
|
-
producerFactId
|
|
18505
|
+
producerFactId,
|
|
18506
|
+
observedAtMs,
|
|
18507
|
+
isHeartbeat: false
|
|
18255
18508
|
});
|
|
18256
|
-
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId);
|
|
18509
|
+
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId, false);
|
|
18257
18510
|
if (ap) {
|
|
18258
18511
|
ap.lastActivityKind = activityKind;
|
|
18259
18512
|
ap.lastActivity = activityDisplay;
|
|
@@ -18270,6 +18523,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18270
18523
|
const heartbeatLaunchId = launchIdOverride || ap.launchId || void 0;
|
|
18271
18524
|
const heartbeatClientSeq = this.nextActivityClientSeq(agentId);
|
|
18272
18525
|
const heartbeatProducerFactId = this.buildActivityProducerFactId(agentId, heartbeatLaunchId, heartbeatClientSeq);
|
|
18526
|
+
const heartbeatObservedAtMs = Date.now();
|
|
18273
18527
|
this.sendToServer({
|
|
18274
18528
|
type: "agent:activity",
|
|
18275
18529
|
agentId,
|
|
@@ -18279,9 +18533,13 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18279
18533
|
detailKind: ap.lastActivityDetailKind,
|
|
18280
18534
|
launchId: heartbeatLaunchId,
|
|
18281
18535
|
clientSeq: heartbeatClientSeq,
|
|
18282
|
-
producerFactId: heartbeatProducerFactId
|
|
18536
|
+
producerFactId: heartbeatProducerFactId,
|
|
18537
|
+
observedAtMs: heartbeatObservedAtMs,
|
|
18538
|
+
// The one knowing site: this timer re-broadcasts stale
|
|
18539
|
+
// lastActivity, so it declares its replay provenance.
|
|
18540
|
+
isHeartbeat: true
|
|
18283
18541
|
});
|
|
18284
|
-
this.recordActivityProducedTrace(agentId, ap.lastActivityKind, ap.lastActivityDetail, ap.lastActivityDetailKind, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId);
|
|
18542
|
+
this.recordActivityProducedTrace(agentId, ap.lastActivityKind, ap.lastActivityDetail, ap.lastActivityDetailKind, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId, true);
|
|
18285
18543
|
}, ACTIVITY_HEARTBEAT_MS);
|
|
18286
18544
|
ap.activityHeartbeat = { kind: "active", timer };
|
|
18287
18545
|
}
|
|
@@ -18290,7 +18548,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18290
18548
|
}
|
|
18291
18549
|
}
|
|
18292
18550
|
}
|
|
18293
|
-
recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId) {
|
|
18551
|
+
recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId, isHeartbeat) {
|
|
18294
18552
|
const runtimeContext = ap?.config.runtimeContext;
|
|
18295
18553
|
this.recordDaemonTrace("daemon.agent.activity.produced", {
|
|
18296
18554
|
agentId,
|
|
@@ -18312,6 +18570,11 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18312
18570
|
client_seq_present: typeof clientSeq === "number",
|
|
18313
18571
|
producerFactId,
|
|
18314
18572
|
producer_fact_id: producerFactId,
|
|
18573
|
+
// #460 V1: the wire's producer-declared replay-provenance bit must be
|
|
18574
|
+
// independently verifiable from daemon-side evidence (L2<->L3 seam);
|
|
18575
|
+
// closed boolean, mirrors the agent:activity isHeartbeat field exactly.
|
|
18576
|
+
isHeartbeat,
|
|
18577
|
+
is_heartbeat: isHeartbeat,
|
|
18315
18578
|
correlation_id: `agent:${agentId}:daemonActivity:${launchId ?? "legacy"}:${clientSeq ?? "unsequenced"}`,
|
|
18316
18579
|
session_id_present: Boolean(ap?.sessionId),
|
|
18317
18580
|
runtime: ap?.config.runtime
|
|
@@ -18360,9 +18623,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18360
18623
|
launchId,
|
|
18361
18624
|
probeId,
|
|
18362
18625
|
clientSeq,
|
|
18363
|
-
producerFactId
|
|
18626
|
+
producerFactId,
|
|
18627
|
+
isHeartbeat: false
|
|
18364
18628
|
});
|
|
18365
|
-
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, [], ap, launchId, clientSeq, producerFactId);
|
|
18629
|
+
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, [], ap, launchId, clientSeq, producerFactId, false);
|
|
18366
18630
|
}
|
|
18367
18631
|
flushPendingTrajectory(agentId) {
|
|
18368
18632
|
const ap = this.agents.get(agentId);
|
|
@@ -21302,6 +21566,563 @@ function assertLegacyDaemonKeyNotAdoptedByComputer(options) {
|
|
|
21302
21566
|
if (match) throw new LegacyDaemonKeyAdoptedByComputerError(match);
|
|
21303
21567
|
}
|
|
21304
21568
|
|
|
21569
|
+
// src/agentMigrationExport.ts
|
|
21570
|
+
import { createHash as createHash7 } from "crypto";
|
|
21571
|
+
import { createReadStream } from "fs";
|
|
21572
|
+
import { lstat as lstat2, readdir as readdir4, readFile as readFile3, readlink } from "fs/promises";
|
|
21573
|
+
import path19 from "path";
|
|
21574
|
+
var AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION = "agent-bundle/v1";
|
|
21575
|
+
var REGENERABLE_DIRECTORY_NAMES = [
|
|
21576
|
+
".venv",
|
|
21577
|
+
"__pycache__",
|
|
21578
|
+
"dist",
|
|
21579
|
+
"node_modules",
|
|
21580
|
+
"target"
|
|
21581
|
+
];
|
|
21582
|
+
var SECRET_FILE_NAMES = /* @__PURE__ */ new Set([
|
|
21583
|
+
".env",
|
|
21584
|
+
".env.local",
|
|
21585
|
+
".env.development",
|
|
21586
|
+
".env.production",
|
|
21587
|
+
".env.test",
|
|
21588
|
+
"credentials.json",
|
|
21589
|
+
"credential.json"
|
|
21590
|
+
]);
|
|
21591
|
+
var ENV_KEY_PATTERN = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
21592
|
+
async function buildAgentMigrationExportManifest(input) {
|
|
21593
|
+
const slockHome = path19.resolve(input.slockHome);
|
|
21594
|
+
const workspace = path19.resolve(input.workspacePath ?? path19.join(slockHome, "agents", input.agentId));
|
|
21595
|
+
const proposedIncludes = normalizeProposalPaths(input.cooperativeManifest?.include, workspace, "include");
|
|
21596
|
+
const proposedRegenerableExcludes = normalizeProposalPaths(input.cooperativeManifest?.exclude_regenerable, workspace, "exclude_regenerable");
|
|
21597
|
+
const cleanedProposal = normalizeProposalPaths(input.cooperativeManifest?.cleaned, workspace, "cleaned");
|
|
21598
|
+
const state = {
|
|
21599
|
+
workspace,
|
|
21600
|
+
files: [],
|
|
21601
|
+
excludedRegenerable: [],
|
|
21602
|
+
promotedIncludes: [],
|
|
21603
|
+
proposalRefusals: [
|
|
21604
|
+
...proposedIncludes.refusals,
|
|
21605
|
+
...proposedRegenerableExcludes.refusals,
|
|
21606
|
+
...cleanedProposal.refusals
|
|
21607
|
+
],
|
|
21608
|
+
unreachable: [],
|
|
21609
|
+
secretsDisclosed: [],
|
|
21610
|
+
seenWorkspacePaths: /* @__PURE__ */ new Set(),
|
|
21611
|
+
explicitIncludePaths: new Set(proposedIncludes.paths)
|
|
21612
|
+
};
|
|
21613
|
+
await walkWorkspace(workspace, "", new Set(proposedRegenerableExcludes.paths), state, { forceIncludeRegenerable: false });
|
|
21614
|
+
for (const requestedPath of proposedIncludes.paths) {
|
|
21615
|
+
if (!state.seenWorkspacePaths.has(requestedPath)) {
|
|
21616
|
+
await includeWorkspacePath(requestedPath, state, { forceIncludeRegenerable: true });
|
|
21617
|
+
}
|
|
21618
|
+
}
|
|
21619
|
+
for (const requestedPath of proposedRegenerableExcludes.paths) {
|
|
21620
|
+
if (isRegenerablePath(requestedPath)) continue;
|
|
21621
|
+
state.promotedIncludes.push({ path: requestedPath, reason: "exclude_not_regenerable" });
|
|
21622
|
+
await includeWorkspacePath(requestedPath, state, { forceIncludeRegenerable: true });
|
|
21623
|
+
}
|
|
21624
|
+
const crossTreeRefs = await buildCrossTreeRefs(input.runtimeSessionRefs ?? []);
|
|
21625
|
+
const secretDisclosureProposal = normalizeProposalPaths(input.cooperativeManifest?.secrets_disclosed, workspace, "secrets_disclosed");
|
|
21626
|
+
state.proposalRefusals.push(...secretDisclosureProposal.refusals);
|
|
21627
|
+
return {
|
|
21628
|
+
schemaVersion: AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION,
|
|
21629
|
+
agentId: input.agentId,
|
|
21630
|
+
mode: input.mode,
|
|
21631
|
+
createdAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
21632
|
+
roots: {
|
|
21633
|
+
slockHome,
|
|
21634
|
+
workspace
|
|
21635
|
+
},
|
|
21636
|
+
defaults: {
|
|
21637
|
+
unknownFiles: "include",
|
|
21638
|
+
excludePolicy: "regenerable_only",
|
|
21639
|
+
regenerableDirectoryNames: [...REGENERABLE_DIRECTORY_NAMES]
|
|
21640
|
+
},
|
|
21641
|
+
files: sortBundleEntries(state.files),
|
|
21642
|
+
excludedRegenerable: sortByPath(state.excludedRegenerable),
|
|
21643
|
+
promotedIncludes: sortByPath(state.promotedIncludes),
|
|
21644
|
+
proposalRefusals: sortByPath(state.proposalRefusals),
|
|
21645
|
+
unreachable: sortByPath(state.unreachable),
|
|
21646
|
+
secretsDisclosed: sortByPath([
|
|
21647
|
+
...state.secretsDisclosed,
|
|
21648
|
+
...normalizeProvidedSecretDisclosures(secretDisclosureProposal.paths)
|
|
21649
|
+
]),
|
|
21650
|
+
cleaned: cleanedProposal.paths,
|
|
21651
|
+
crossTreeRefs: crossTreeRefs.sort((a, b) => a.bundlePath.localeCompare(b.bundlePath))
|
|
21652
|
+
};
|
|
21653
|
+
}
|
|
21654
|
+
async function walkWorkspace(root, relativeDir, proposedRegenerableExcludes, state, opts) {
|
|
21655
|
+
const absoluteDir = path19.join(root, relativeDir);
|
|
21656
|
+
let entries;
|
|
21657
|
+
try {
|
|
21658
|
+
entries = await readdir4(absoluteDir, { withFileTypes: true });
|
|
21659
|
+
} catch {
|
|
21660
|
+
state.unreachable.push({
|
|
21661
|
+
path: relativeDir || ".",
|
|
21662
|
+
sourcePath: absoluteDir,
|
|
21663
|
+
reason: "read_error"
|
|
21664
|
+
});
|
|
21665
|
+
return;
|
|
21666
|
+
}
|
|
21667
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
21668
|
+
for (const entry of entries) {
|
|
21669
|
+
const relativePath = toPosixPath(path19.join(relativeDir, entry.name));
|
|
21670
|
+
if (entry.isDirectory()) {
|
|
21671
|
+
if (!opts.forceIncludeRegenerable && isRegenerablePath(relativePath)) {
|
|
21672
|
+
if (state.explicitIncludePaths.has(relativePath)) {
|
|
21673
|
+
await walkWorkspace(root, relativePath, proposedRegenerableExcludes, state, { forceIncludeRegenerable: true });
|
|
21674
|
+
continue;
|
|
21675
|
+
}
|
|
21676
|
+
if (hasExplicitIncludeDescendant(relativePath, state.explicitIncludePaths)) {
|
|
21677
|
+
await walkWorkspace(root, relativePath, proposedRegenerableExcludes, state, opts);
|
|
21678
|
+
continue;
|
|
21679
|
+
}
|
|
21680
|
+
state.excludedRegenerable.push({
|
|
21681
|
+
path: relativePath,
|
|
21682
|
+
reason: proposedRegenerableExcludes.has(relativePath) ? "cooperative_exclude_regenerable" : "regenerable_default",
|
|
21683
|
+
regenerableHint: `${entry.name} is treated as rebuildable/installable state and is not bundled by default`
|
|
21684
|
+
});
|
|
21685
|
+
continue;
|
|
21686
|
+
}
|
|
21687
|
+
await walkWorkspace(root, relativePath, proposedRegenerableExcludes, state, opts);
|
|
21688
|
+
continue;
|
|
21689
|
+
}
|
|
21690
|
+
await includeWorkspacePath(relativePath, state, { forceIncludeRegenerable: opts.forceIncludeRegenerable });
|
|
21691
|
+
}
|
|
21692
|
+
}
|
|
21693
|
+
async function includeWorkspacePath(workspaceRelativePath, state, opts) {
|
|
21694
|
+
const normalizedRelativePath = normalizeRelativePath(workspaceRelativePath);
|
|
21695
|
+
if (state.seenWorkspacePaths.has(normalizedRelativePath)) return;
|
|
21696
|
+
const sourcePath = path19.join(state.workspace, normalizedRelativePath);
|
|
21697
|
+
let stat4;
|
|
21698
|
+
try {
|
|
21699
|
+
stat4 = await lstat2(sourcePath);
|
|
21700
|
+
} catch {
|
|
21701
|
+
state.unreachable.push({
|
|
21702
|
+
path: normalizedRelativePath,
|
|
21703
|
+
sourcePath,
|
|
21704
|
+
reason: "missing"
|
|
21705
|
+
});
|
|
21706
|
+
return;
|
|
21707
|
+
}
|
|
21708
|
+
if (stat4.isDirectory()) {
|
|
21709
|
+
if (!opts.forceIncludeRegenerable && isRegenerablePath(normalizedRelativePath)) {
|
|
21710
|
+
state.excludedRegenerable.push({
|
|
21711
|
+
path: normalizedRelativePath,
|
|
21712
|
+
reason: "cooperative_exclude_regenerable",
|
|
21713
|
+
regenerableHint: `${path19.basename(normalizedRelativePath)} is treated as rebuildable/installable state and is not bundled by default`
|
|
21714
|
+
});
|
|
21715
|
+
return;
|
|
21716
|
+
}
|
|
21717
|
+
await walkWorkspace(state.workspace, normalizedRelativePath, /* @__PURE__ */ new Set(), state, opts);
|
|
21718
|
+
return;
|
|
21719
|
+
}
|
|
21720
|
+
state.seenWorkspacePaths.add(normalizedRelativePath);
|
|
21721
|
+
const baseEntry = {
|
|
21722
|
+
source: "workspace",
|
|
21723
|
+
sourcePath,
|
|
21724
|
+
workspaceRelativePath: normalizedRelativePath,
|
|
21725
|
+
bundlePath: `workspace/${normalizedRelativePath}`,
|
|
21726
|
+
mode: stat4.mode,
|
|
21727
|
+
mtimeMs: stat4.mtimeMs
|
|
21728
|
+
};
|
|
21729
|
+
if (stat4.isSymbolicLink()) {
|
|
21730
|
+
state.files.push({
|
|
21731
|
+
...baseEntry,
|
|
21732
|
+
kind: "symlink",
|
|
21733
|
+
linkTarget: await readlink(sourcePath)
|
|
21734
|
+
});
|
|
21735
|
+
return;
|
|
21736
|
+
}
|
|
21737
|
+
if (!stat4.isFile()) {
|
|
21738
|
+
state.unreachable.push({
|
|
21739
|
+
path: normalizedRelativePath,
|
|
21740
|
+
sourcePath,
|
|
21741
|
+
reason: "unsupported_file_type"
|
|
21742
|
+
});
|
|
21743
|
+
return;
|
|
21744
|
+
}
|
|
21745
|
+
const secretShapes = await detectSecretShapes(sourcePath, normalizedRelativePath);
|
|
21746
|
+
if (secretShapes.length > 0) {
|
|
21747
|
+
state.secretsDisclosed.push({ path: normalizedRelativePath, shapes: secretShapes });
|
|
21748
|
+
}
|
|
21749
|
+
state.files.push({
|
|
21750
|
+
...baseEntry,
|
|
21751
|
+
kind: "file",
|
|
21752
|
+
sizeBytes: stat4.size,
|
|
21753
|
+
sha256: await sha256File(sourcePath),
|
|
21754
|
+
secretShapes: secretShapes.length > 0 ? secretShapes : void 0
|
|
21755
|
+
});
|
|
21756
|
+
}
|
|
21757
|
+
async function buildCrossTreeRefs(refs) {
|
|
21758
|
+
const result = [];
|
|
21759
|
+
for (const ref of refs) {
|
|
21760
|
+
const sourcePath = path19.resolve(ref.path);
|
|
21761
|
+
const bundlePath = `runtime/${safeBundleSegment(ref.runtime)}/${safeBundleSegment(ref.label)}/${safeBundleSegment(path19.basename(sourcePath) || "session")}`;
|
|
21762
|
+
const entry = {
|
|
21763
|
+
runtime: ref.runtime,
|
|
21764
|
+
label: ref.label,
|
|
21765
|
+
sourcePath,
|
|
21766
|
+
bundlePath,
|
|
21767
|
+
reachable: ref.reachable !== false,
|
|
21768
|
+
reason: ref.reason
|
|
21769
|
+
};
|
|
21770
|
+
try {
|
|
21771
|
+
const stat4 = await lstat2(sourcePath);
|
|
21772
|
+
if (stat4.isFile()) {
|
|
21773
|
+
entry.sizeBytes = stat4.size;
|
|
21774
|
+
entry.sha256 = await sha256File(sourcePath);
|
|
21775
|
+
}
|
|
21776
|
+
} catch {
|
|
21777
|
+
entry.reachable = false;
|
|
21778
|
+
}
|
|
21779
|
+
result.push(entry);
|
|
21780
|
+
}
|
|
21781
|
+
return result;
|
|
21782
|
+
}
|
|
21783
|
+
async function sha256File(filePath) {
|
|
21784
|
+
const hash = createHash7("sha256");
|
|
21785
|
+
await new Promise((resolve, reject) => {
|
|
21786
|
+
const stream = createReadStream(filePath);
|
|
21787
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
21788
|
+
stream.on("error", reject);
|
|
21789
|
+
stream.on("end", resolve);
|
|
21790
|
+
});
|
|
21791
|
+
return hash.digest("hex");
|
|
21792
|
+
}
|
|
21793
|
+
async function detectSecretShapes(sourcePath, relativePath) {
|
|
21794
|
+
const basename = path19.basename(relativePath);
|
|
21795
|
+
const lowerBasename = basename.toLowerCase();
|
|
21796
|
+
const shapes = /* @__PURE__ */ new Set();
|
|
21797
|
+
if (SECRET_FILE_NAMES.has(lowerBasename) || lowerBasename.startsWith(".env.")) {
|
|
21798
|
+
shapes.add(`file:${basename}`);
|
|
21799
|
+
try {
|
|
21800
|
+
const text = await readFile3(sourcePath, "utf8");
|
|
21801
|
+
for (const line of text.split(/\r?\n/)) {
|
|
21802
|
+
const match = ENV_KEY_PATTERN.exec(line);
|
|
21803
|
+
if (match) shapes.add(`env:${match[1]}`);
|
|
21804
|
+
}
|
|
21805
|
+
} catch {
|
|
21806
|
+
shapes.add("content:unreadable");
|
|
21807
|
+
}
|
|
21808
|
+
}
|
|
21809
|
+
if (/(?:secret|token|credential|api[-_]?key)/i.test(relativePath)) {
|
|
21810
|
+
shapes.add(`path:${basename}`);
|
|
21811
|
+
}
|
|
21812
|
+
return [...shapes].sort();
|
|
21813
|
+
}
|
|
21814
|
+
function normalizeProvidedSecretDisclosures(disclosures) {
|
|
21815
|
+
return disclosures.map((entry) => ({
|
|
21816
|
+
path: entry,
|
|
21817
|
+
shapes: ["provided"]
|
|
21818
|
+
}));
|
|
21819
|
+
}
|
|
21820
|
+
function normalizeProposalPaths(paths, workspace, source) {
|
|
21821
|
+
if (!paths) return { paths: [], refusals: [] };
|
|
21822
|
+
const result = [];
|
|
21823
|
+
const refusals = [];
|
|
21824
|
+
for (const value of paths) {
|
|
21825
|
+
const trimmed = value.trim();
|
|
21826
|
+
if (!trimmed) continue;
|
|
21827
|
+
if (path19.isAbsolute(trimmed)) {
|
|
21828
|
+
const relative = path19.relative(workspace, trimmed);
|
|
21829
|
+
if (relative.startsWith("..") || path19.isAbsolute(relative)) {
|
|
21830
|
+
refusals.push({
|
|
21831
|
+
path: trimmed,
|
|
21832
|
+
reason: "outside_workspace",
|
|
21833
|
+
source
|
|
21834
|
+
});
|
|
21835
|
+
continue;
|
|
21836
|
+
}
|
|
21837
|
+
try {
|
|
21838
|
+
result.push(normalizeRelativePath(relative));
|
|
21839
|
+
} catch {
|
|
21840
|
+
refusals.push({
|
|
21841
|
+
path: trimmed,
|
|
21842
|
+
reason: "unsafe_path",
|
|
21843
|
+
source
|
|
21844
|
+
});
|
|
21845
|
+
}
|
|
21846
|
+
continue;
|
|
21847
|
+
}
|
|
21848
|
+
try {
|
|
21849
|
+
result.push(normalizeRelativePath(trimmed));
|
|
21850
|
+
} catch {
|
|
21851
|
+
refusals.push({
|
|
21852
|
+
path: trimmed,
|
|
21853
|
+
reason: "unsafe_path",
|
|
21854
|
+
source
|
|
21855
|
+
});
|
|
21856
|
+
}
|
|
21857
|
+
}
|
|
21858
|
+
return { paths: [...new Set(result)], refusals };
|
|
21859
|
+
}
|
|
21860
|
+
function normalizeRelativePath(value) {
|
|
21861
|
+
const normalized = path19.normalize(value).replace(/^[\\/]+/, "");
|
|
21862
|
+
if (!normalized || normalized === "." || normalized.startsWith("..") || path19.isAbsolute(normalized)) {
|
|
21863
|
+
throw new Error(`unsafe migration export path: ${value}`);
|
|
21864
|
+
}
|
|
21865
|
+
return toPosixPath(normalized);
|
|
21866
|
+
}
|
|
21867
|
+
function isRegenerablePath(relativePath) {
|
|
21868
|
+
return normalizeRelativePath(relativePath).split("/").some((segment) => REGENERABLE_DIRECTORY_NAMES.includes(segment));
|
|
21869
|
+
}
|
|
21870
|
+
function hasExplicitIncludeDescendant(relativePath, explicitIncludePaths) {
|
|
21871
|
+
const prefix = `${relativePath}/`;
|
|
21872
|
+
for (const includePath of explicitIncludePaths) {
|
|
21873
|
+
if (includePath.startsWith(prefix)) return true;
|
|
21874
|
+
}
|
|
21875
|
+
return false;
|
|
21876
|
+
}
|
|
21877
|
+
function safeBundleSegment(value) {
|
|
21878
|
+
return value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
|
|
21879
|
+
}
|
|
21880
|
+
function toPosixPath(value) {
|
|
21881
|
+
return value.split(path19.sep).join("/");
|
|
21882
|
+
}
|
|
21883
|
+
function sortBundleEntries(entries) {
|
|
21884
|
+
return [...entries].sort((a, b) => a.bundlePath.localeCompare(b.bundlePath));
|
|
21885
|
+
}
|
|
21886
|
+
function sortByPath(entries) {
|
|
21887
|
+
return [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
21888
|
+
}
|
|
21889
|
+
|
|
21890
|
+
// src/agentMigrationHttpTransport.ts
|
|
21891
|
+
import { createHash as createHash8, randomBytes as randomBytes2, timingSafeEqual } from "crypto";
|
|
21892
|
+
import http2 from "http";
|
|
21893
|
+
var MigrationBundleStreamError = class extends Error {
|
|
21894
|
+
constructor(code) {
|
|
21895
|
+
super(code);
|
|
21896
|
+
this.code = code;
|
|
21897
|
+
}
|
|
21898
|
+
};
|
|
21899
|
+
var AgentMigrationGrantRegistry = class {
|
|
21900
|
+
grants = /* @__PURE__ */ new Map();
|
|
21901
|
+
now;
|
|
21902
|
+
constructor(now = () => /* @__PURE__ */ new Date()) {
|
|
21903
|
+
this.now = now;
|
|
21904
|
+
}
|
|
21905
|
+
createGrant(input) {
|
|
21906
|
+
const token = input.token ?? randomBytes2(32).toString("base64url");
|
|
21907
|
+
const manifestSha256 = sha256Buffer(canonicalJsonBuffer(input.manifest));
|
|
21908
|
+
const grant = {
|
|
21909
|
+
grantId: input.grantId ?? randomBytes2(16).toString("hex"),
|
|
21910
|
+
tokenHash: hashToken(token),
|
|
21911
|
+
expiresAt: input.expiresAt,
|
|
21912
|
+
oneTimeUse: input.oneTimeUse ?? true,
|
|
21913
|
+
state: "issued",
|
|
21914
|
+
manifest: input.manifest,
|
|
21915
|
+
manifestSha256,
|
|
21916
|
+
bundleEtag: `"agent-migration-${manifestSha256}"`
|
|
21917
|
+
};
|
|
21918
|
+
this.grants.set(grant.grantId, grant);
|
|
21919
|
+
return { grant, token };
|
|
21920
|
+
}
|
|
21921
|
+
get(grantId) {
|
|
21922
|
+
return this.grants.get(grantId);
|
|
21923
|
+
}
|
|
21924
|
+
authenticate(grantId, token) {
|
|
21925
|
+
const grant = this.grants.get(grantId);
|
|
21926
|
+
if (!grant || !token || !verifyTokenHash(token, grant.tokenHash)) {
|
|
21927
|
+
return { ok: false, status: 401, code: "migration_grant_auth_failed" };
|
|
21928
|
+
}
|
|
21929
|
+
if (grant.state === "revoked" || grant.state === "consumed") {
|
|
21930
|
+
return { ok: false, status: 410, code: "migration_grant_unavailable" };
|
|
21931
|
+
}
|
|
21932
|
+
if (this.now().getTime() >= grant.expiresAt.getTime()) {
|
|
21933
|
+
grant.state = "expired";
|
|
21934
|
+
return { ok: false, status: 410, code: "migration_grant_unavailable" };
|
|
21935
|
+
}
|
|
21936
|
+
return { ok: true, grant };
|
|
21937
|
+
}
|
|
21938
|
+
revokeAll() {
|
|
21939
|
+
for (const grant of this.grants.values()) {
|
|
21940
|
+
if (grant.state !== "consumed" && grant.state !== "expired") {
|
|
21941
|
+
grant.state = "revoked";
|
|
21942
|
+
}
|
|
21943
|
+
}
|
|
21944
|
+
}
|
|
21945
|
+
};
|
|
21946
|
+
function createAgentMigrationHttpTransport(options = {}) {
|
|
21947
|
+
const registry = new AgentMigrationGrantRegistry(options.now);
|
|
21948
|
+
const bundleStreamFactory = options.bundleStreamFactory ?? defaultBundleStream;
|
|
21949
|
+
const server = http2.createServer((req, res) => {
|
|
21950
|
+
void handleMigrationRequest(req, res, registry, bundleStreamFactory);
|
|
21951
|
+
});
|
|
21952
|
+
return {
|
|
21953
|
+
grants: registry,
|
|
21954
|
+
server,
|
|
21955
|
+
listen: (port = 0, host = "127.0.0.1") => new Promise((resolve, reject) => {
|
|
21956
|
+
server.once("error", reject);
|
|
21957
|
+
server.listen(port, host, () => {
|
|
21958
|
+
server.off("error", reject);
|
|
21959
|
+
const address = server.address();
|
|
21960
|
+
if (!address || typeof address === "string") {
|
|
21961
|
+
reject(new Error("migration transport listen did not produce a TCP address"));
|
|
21962
|
+
return;
|
|
21963
|
+
}
|
|
21964
|
+
resolve({ url: `http://${address.address}:${address.port}` });
|
|
21965
|
+
});
|
|
21966
|
+
}),
|
|
21967
|
+
close: () => new Promise((resolve, reject) => {
|
|
21968
|
+
registry.revokeAll();
|
|
21969
|
+
server.close((err) => {
|
|
21970
|
+
if (err) reject(err);
|
|
21971
|
+
else resolve();
|
|
21972
|
+
});
|
|
21973
|
+
})
|
|
21974
|
+
};
|
|
21975
|
+
}
|
|
21976
|
+
async function handleMigrationRequest(req, res, registry, bundleStreamFactory) {
|
|
21977
|
+
const parsed = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
21978
|
+
const match = /^\/migration\/([^/]+)\/([^/]+)(?:\/([^/]+))?$/.exec(parsed.pathname);
|
|
21979
|
+
if (!match) {
|
|
21980
|
+
sendJson(res, 404, { code: "migration_route_not_found" });
|
|
21981
|
+
return;
|
|
21982
|
+
}
|
|
21983
|
+
const [, grantId, resource, resourceId] = match;
|
|
21984
|
+
const auth = registry.authenticate(decodeURIComponent(grantId), extractBearerToken(req));
|
|
21985
|
+
if (!auth.ok) {
|
|
21986
|
+
sendJson(res, auth.status, { code: auth.code });
|
|
21987
|
+
return;
|
|
21988
|
+
}
|
|
21989
|
+
if (resource === "manifest" && req.method === "GET" && !resourceId) {
|
|
21990
|
+
sendJson(res, 200, {
|
|
21991
|
+
manifestSha256: auth.grant.manifestSha256,
|
|
21992
|
+
manifest: auth.grant.manifest
|
|
21993
|
+
}, {
|
|
21994
|
+
"X-Raft-Manifest-Sha": auth.grant.manifestSha256,
|
|
21995
|
+
ETag: `"manifest-${auth.grant.manifestSha256}"`
|
|
21996
|
+
});
|
|
21997
|
+
return;
|
|
21998
|
+
}
|
|
21999
|
+
if (resource === "bundle.tar" && !resourceId) {
|
|
22000
|
+
if (req.method === "HEAD") {
|
|
22001
|
+
sendHead(res, auth.grant);
|
|
22002
|
+
return;
|
|
22003
|
+
}
|
|
22004
|
+
if (req.method === "GET") {
|
|
22005
|
+
await streamBundle(res, auth.grant, bundleStreamFactory);
|
|
22006
|
+
return;
|
|
22007
|
+
}
|
|
22008
|
+
}
|
|
22009
|
+
if (resource === "chunk" && req.method === "GET" && resourceId) {
|
|
22010
|
+
sendJson(res, 501, { code: "migration_chunk_not_implemented" });
|
|
22011
|
+
return;
|
|
22012
|
+
}
|
|
22013
|
+
sendJson(res, 405, { code: "migration_method_not_allowed" });
|
|
22014
|
+
}
|
|
22015
|
+
function sendHead(res, grant) {
|
|
22016
|
+
res.statusCode = 200;
|
|
22017
|
+
res.setHeader("X-Raft-Manifest-Sha", grant.manifestSha256);
|
|
22018
|
+
res.setHeader("ETag", grant.bundleEtag);
|
|
22019
|
+
res.setHeader("Accept-Ranges", "none");
|
|
22020
|
+
res.setHeader("X-Raft-Bundle-Size", "unknown");
|
|
22021
|
+
res.end();
|
|
22022
|
+
}
|
|
22023
|
+
async function streamBundle(res, grant, bundleStreamFactory) {
|
|
22024
|
+
if (grant.state === "streaming") {
|
|
22025
|
+
sendJson(res, 409, { code: "migration_bundle_stream_in_progress" });
|
|
22026
|
+
return;
|
|
22027
|
+
}
|
|
22028
|
+
if (grant.oneTimeUse && grant.state !== "issued" && grant.state !== "interrupted") {
|
|
22029
|
+
sendJson(res, 410, { code: "migration_grant_unavailable" });
|
|
22030
|
+
return;
|
|
22031
|
+
}
|
|
22032
|
+
let stream;
|
|
22033
|
+
try {
|
|
22034
|
+
stream = bundleStreamFactory(grant);
|
|
22035
|
+
} catch (err) {
|
|
22036
|
+
const code = err instanceof MigrationBundleStreamError ? err.code : "migration_bundle_stream_failed";
|
|
22037
|
+
sendJson(res, 500, { code });
|
|
22038
|
+
return;
|
|
22039
|
+
}
|
|
22040
|
+
grant.state = "streaming";
|
|
22041
|
+
let completed = false;
|
|
22042
|
+
res.on("close", () => {
|
|
22043
|
+
if (!completed && grant.state === "streaming") {
|
|
22044
|
+
grant.state = "interrupted";
|
|
22045
|
+
}
|
|
22046
|
+
});
|
|
22047
|
+
try {
|
|
22048
|
+
res.statusCode = 200;
|
|
22049
|
+
res.setHeader("Content-Type", "application/x-tar");
|
|
22050
|
+
res.setHeader("X-Raft-Manifest-Sha", grant.manifestSha256);
|
|
22051
|
+
res.setHeader("ETag", grant.bundleEtag);
|
|
22052
|
+
for await (const chunk of stream) {
|
|
22053
|
+
if (!res.write(chunk)) {
|
|
22054
|
+
await onceDrain(res);
|
|
22055
|
+
}
|
|
22056
|
+
}
|
|
22057
|
+
completed = true;
|
|
22058
|
+
grant.state = "consumed";
|
|
22059
|
+
res.end();
|
|
22060
|
+
} catch {
|
|
22061
|
+
if (!completed && grant.state === "streaming") {
|
|
22062
|
+
grant.state = "interrupted";
|
|
22063
|
+
}
|
|
22064
|
+
if (!res.headersSent) {
|
|
22065
|
+
sendJson(res, 500, { code: "migration_bundle_stream_failed" });
|
|
22066
|
+
} else {
|
|
22067
|
+
res.destroy();
|
|
22068
|
+
}
|
|
22069
|
+
}
|
|
22070
|
+
}
|
|
22071
|
+
function defaultBundleStream(grant) {
|
|
22072
|
+
void grant;
|
|
22073
|
+
throw new MigrationBundleStreamError("migration_bundle_stream_not_wired");
|
|
22074
|
+
}
|
|
22075
|
+
function extractBearerToken(req) {
|
|
22076
|
+
const directHeader = singleHeader(req.headers["x-raft-migration-token"]);
|
|
22077
|
+
if (directHeader) return directHeader;
|
|
22078
|
+
const authorization = singleHeader(req.headers.authorization);
|
|
22079
|
+
if (!authorization) return null;
|
|
22080
|
+
const match = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
22081
|
+
return match?.[1] ?? null;
|
|
22082
|
+
}
|
|
22083
|
+
function singleHeader(value) {
|
|
22084
|
+
if (!value) return null;
|
|
22085
|
+
return Array.isArray(value) ? value[0] ?? null : value;
|
|
22086
|
+
}
|
|
22087
|
+
function sendJson(res, status, body, headers = {}) {
|
|
22088
|
+
const payload = JSON.stringify(body);
|
|
22089
|
+
res.writeHead(status, {
|
|
22090
|
+
"Content-Type": "application/json",
|
|
22091
|
+
"Content-Length": Buffer.byteLength(payload).toString(),
|
|
22092
|
+
...headers
|
|
22093
|
+
});
|
|
22094
|
+
res.end(payload);
|
|
22095
|
+
}
|
|
22096
|
+
function hashToken(token) {
|
|
22097
|
+
return sha256Buffer(Buffer.from(token, "utf8"));
|
|
22098
|
+
}
|
|
22099
|
+
function verifyTokenHash(token, expectedHashHex) {
|
|
22100
|
+
const actual = Buffer.from(hashToken(token), "hex");
|
|
22101
|
+
const expected = Buffer.from(expectedHashHex, "hex");
|
|
22102
|
+
if (actual.byteLength !== expected.byteLength) return false;
|
|
22103
|
+
return timingSafeEqual(actual, expected);
|
|
22104
|
+
}
|
|
22105
|
+
function sha256Buffer(buffer) {
|
|
22106
|
+
return createHash8("sha256").update(buffer).digest("hex");
|
|
22107
|
+
}
|
|
22108
|
+
function canonicalJsonBuffer(value) {
|
|
22109
|
+
return Buffer.from(canonicalJson(value), "utf8");
|
|
22110
|
+
}
|
|
22111
|
+
function canonicalJson(value) {
|
|
22112
|
+
return JSON.stringify(sortJsonValue(value));
|
|
22113
|
+
}
|
|
22114
|
+
function sortJsonValue(value) {
|
|
22115
|
+
if (Array.isArray(value)) return value.map(sortJsonValue);
|
|
22116
|
+
if (!value || typeof value !== "object") return value;
|
|
22117
|
+
return Object.keys(value).sort().reduce((result, key) => {
|
|
22118
|
+
result[key] = sortJsonValue(value[key]);
|
|
22119
|
+
return result;
|
|
22120
|
+
}, {});
|
|
22121
|
+
}
|
|
22122
|
+
function onceDrain(res) {
|
|
22123
|
+
return new Promise((resolve) => res.once("drain", resolve));
|
|
22124
|
+
}
|
|
22125
|
+
|
|
21305
22126
|
// src/core.ts
|
|
21306
22127
|
var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
|
|
21307
22128
|
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
|
|
@@ -21409,7 +22230,17 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
21409
22230
|
spanAttrs: ["running_agents_count", "idle_agents_count"]
|
|
21410
22231
|
},
|
|
21411
22232
|
"daemon.agent.activity.produced": {
|
|
21412
|
-
|
|
22233
|
+
// isHeartbeat/is_heartbeat (#460 V1) and process_instance_id (#460 V3)
|
|
22234
|
+
// were emitted by agentProcessManager but scrubbed here (pilot violation
|
|
22235
|
+
// V4): this list is a RUNTIME allowlist (SpanAttrContractTracer), so an
|
|
22236
|
+
// emission-site key that is not added here silently dies before disk.
|
|
22237
|
+
// Witness for the pair lives in agentProcessManager.builtin.e2e.test.ts
|
|
22238
|
+
// behind a contract-wrapped tracer (production-isomorphic oracle).
|
|
22239
|
+
// producerFactId/producer_fact_id and activity_kind/detail_kind are ALSO
|
|
22240
|
+
// emitted-and-scrubbed today; deliberately NOT added here — banned-join-
|
|
22241
|
+
// key discipline for the fact id (#460 classification ruling) means
|
|
22242
|
+
// widening needs its own ruling, not a drive-by.
|
|
22243
|
+
spanAttrs: ["agentId", "agent_id", "server_id", "machine_id", "activity", "detail_present", "entry_kinds", "ap_present", "launchId", "launch_id", "launch_id_present", "clientSeq", "client_seq", "client_seq_present", "correlation_id", "session_id_present", "runtime", "isHeartbeat", "is_heartbeat", "process_instance_id"]
|
|
21413
22244
|
},
|
|
21414
22245
|
"daemon.agent.activity.skipped": {
|
|
21415
22246
|
spanAttrs: ["agentId", "event_kind", "reason", "text_length"]
|
|
@@ -21473,13 +22304,13 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
|
|
|
21473
22304
|
}
|
|
21474
22305
|
}
|
|
21475
22306
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
21476
|
-
const thisDir =
|
|
21477
|
-
const bundledDistPath =
|
|
22307
|
+
const thisDir = path20.dirname(fileURLToPath(moduleUrl));
|
|
22308
|
+
const bundledDistPath = path20.resolve(thisDir, "cli", "index.js");
|
|
21478
22309
|
try {
|
|
21479
22310
|
accessSync(bundledDistPath);
|
|
21480
22311
|
return bundledDistPath;
|
|
21481
22312
|
} catch {
|
|
21482
|
-
const workspaceDistPath =
|
|
22313
|
+
const workspaceDistPath = path20.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
|
|
21483
22314
|
accessSync(workspaceDistPath);
|
|
21484
22315
|
return workspaceDistPath;
|
|
21485
22316
|
}
|
|
@@ -21493,7 +22324,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
21493
22324
|
}
|
|
21494
22325
|
async function runBundledSlockCli(argv) {
|
|
21495
22326
|
process.argv = [process.execPath, "slock", ...argv];
|
|
21496
|
-
await import("./dist-
|
|
22327
|
+
await import("./dist-D77BWHH4.js");
|
|
21497
22328
|
}
|
|
21498
22329
|
function detectRuntimes(tracer = noopTracer) {
|
|
21499
22330
|
const ids = [];
|
|
@@ -21701,7 +22532,7 @@ var DaemonCore = class {
|
|
|
21701
22532
|
}
|
|
21702
22533
|
resolveMachineStateRoot() {
|
|
21703
22534
|
if (this.options.machineStateDir) return this.options.machineStateDir;
|
|
21704
|
-
if (this.options.dataDir) return
|
|
22535
|
+
if (this.options.dataDir) return path20.join(path20.dirname(this.options.dataDir), "machines");
|
|
21705
22536
|
return resolveDefaultMachineStateRoot();
|
|
21706
22537
|
}
|
|
21707
22538
|
shouldEnableLocalTrace() {
|
|
@@ -21729,7 +22560,7 @@ var DaemonCore = class {
|
|
|
21729
22560
|
sinks: [this.localTraceSink]
|
|
21730
22561
|
}));
|
|
21731
22562
|
this.agentManager.setTracer(this.tracer);
|
|
21732
|
-
this.agentManager.setCliTransportTraceDir(
|
|
22563
|
+
this.agentManager.setCliTransportTraceDir(path20.join(machineDir, "traces"));
|
|
21733
22564
|
}
|
|
21734
22565
|
installTraceBundleUploader(machineDir) {
|
|
21735
22566
|
if (!this.shouldEnableLocalTrace()) return;
|
|
@@ -22018,7 +22849,7 @@ var DaemonCore = class {
|
|
|
22018
22849
|
session_id_present: Boolean(msg.config.sessionId)
|
|
22019
22850
|
}, "error");
|
|
22020
22851
|
this.connection.send({ type: "agent:status", agentId: msg.agentId, status: "inactive", launchId: msg.launchId });
|
|
22021
|
-
this.connection.send({ type: "agent:activity", agentId: msg.agentId, activity: "offline", detail: classification.userMessage, launchId: msg.launchId });
|
|
22852
|
+
this.connection.send({ type: "agent:activity", agentId: msg.agentId, activity: "offline", detail: classification.userMessage, launchId: msg.launchId, observedAtMs: Date.now() });
|
|
22022
22853
|
});
|
|
22023
22854
|
break;
|
|
22024
22855
|
case "agent:stop":
|
|
@@ -22438,6 +23269,10 @@ export {
|
|
|
22438
23269
|
resolveWorkspaceDirectoryPath,
|
|
22439
23270
|
scanWorkspaceDirectories,
|
|
22440
23271
|
deleteWorkspaceDirectory,
|
|
23272
|
+
AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION,
|
|
23273
|
+
buildAgentMigrationExportManifest,
|
|
23274
|
+
AgentMigrationGrantRegistry,
|
|
23275
|
+
createAgentMigrationHttpTransport,
|
|
22441
23276
|
DAEMON_CORE_TRACE_ATTR_CONTRACTS,
|
|
22442
23277
|
DAEMON_CLI_USAGE,
|
|
22443
23278
|
parseDaemonCliArgs,
|