@huynle/hub 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +296 -0
- package/Dockerfile +5 -1
- package/README.md +152 -77
- package/package.json +7 -4
- package/packages/claude-code/package.json +1 -1
- package/packages/cli/dist/hub-cli.js +532 -261
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/cli.ts +36 -1
- package/packages/cli/src/subscriptions.ts +49 -0
- package/packages/codex/package.json +1 -1
- package/packages/codex/src/sessions.ts +10 -6
- package/packages/codex/src/spoke.ts +2 -1
- package/packages/node/package.json +1 -1
- package/packages/preset/package.json +1 -1
- package/packages/protocol/package.json +1 -1
- package/packages/protocol/schema/app-delivery/v1.schema.json +7 -5
- package/packages/protocol/schema/app-front/v1.schema.json +410 -0
- package/packages/protocol/src/app-front.ts +293 -0
- package/packages/protocol/src/concierge.ts +10 -1
- package/packages/protocol/src/context-cards.ts +59 -0
- package/packages/protocol/src/credentials.ts +39 -2
- package/packages/protocol/src/index.ts +69 -11
- package/packages/runtime-openshell/package.json +1 -1
- package/packages/runtime-sdk/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/packages/sdk/src/app-front.ts +524 -0
- package/packages/sdk/src/client.ts +37 -4
- package/packages/sdk/src/envelope.ts +9 -2
- package/packages/sdk/src/errors.ts +1 -0
- package/packages/sdk/src/index.ts +1 -0
- package/packages/sdk/src/types.ts +39 -1
- package/packages/spoke-sdk/package.json +1 -1
- package/packages/spoke-sdk/src/delivery.ts +17 -1
- package/packages/spoke-sdk/src/harness-spoke.ts +4 -3
- package/packages/voice-client/README.md +146 -0
- package/packages/voice-client/src/vad/LICENSE +21 -0
- package/src/central/agent/acting-routes.ts +17 -3
- package/src/central/agent/acting.ts +12 -3
- package/src/central/agent/actor.ts +6 -1
- package/src/central/agent/app-decisions.ts +146 -0
- package/src/central/agent/app-tokens.ts +9 -3
- package/src/central/agent/audit.ts +3 -0
- package/src/central/agent/connect-routes.ts +64 -0
- package/src/central/agent/connect.ts +868 -0
- package/src/central/agent/conversation.ts +625 -0
- package/src/central/agent/decisions.ts +71 -6
- package/src/central/agent/delivery.ts +3 -0
- package/src/central/agent/directory.ts +5 -0
- package/src/central/agent/errors.ts +2 -0
- package/src/central/agent/grant-requests.ts +46 -9
- package/src/central/agent/grants.ts +13 -2
- package/src/central/agent/message-limits.ts +2 -2
- package/src/central/agent/message-routes.ts +13 -4
- package/src/central/agent/read-routes.ts +16 -2
- package/src/central/agent/routes.ts +108 -6
- package/src/central/agent/speech-routes.ts +316 -0
- package/src/central/agent/subscription-routes.ts +174 -0
- package/src/central/agent/subscriptions.ts +980 -0
- package/src/central/agent-data.ts +43 -1
- package/src/central/backend/memory-counters.ts +2 -2
- package/src/central/backend/types.ts +5 -2
- package/src/central/backend/valkey-counters.ts +5 -4
- package/src/central/client-address.ts +16 -0
- package/src/central/concierge/board-render.ts +52 -1
- package/src/central/concierge/board-routes.ts +25 -2
- package/src/central/concierge/board.ts +11 -1
- package/src/central/concierge/context.ts +29 -8
- package/src/central/concierge/grant-request.ts +216 -0
- package/src/central/concierge/prompt.ts +49 -2
- package/src/central/concierge/session-routes.ts +3 -0
- package/src/central/config.ts +64 -3
- package/src/central/context-cards/budget.ts +121 -0
- package/src/central/context-cards/changes.ts +29 -0
- package/src/central/context-cards/config.ts +145 -0
- package/src/central/context-cards/engine.ts +379 -0
- package/src/central/context-cards/inputs.ts +111 -0
- package/src/central/context-cards/pickup.ts +134 -0
- package/src/central/context-cards/registry.ts +89 -0
- package/src/central/context-cards/routes.ts +37 -0
- package/src/central/context-cards/service.ts +367 -0
- package/src/central/context-cards/store.ts +67 -0
- package/src/central/context-cards/types.ts +88 -0
- package/src/central/fetcher.ts +10 -2
- package/src/central/front-relays.ts +423 -0
- package/src/central/http.ts +516 -56
- package/src/central/human-activity.ts +453 -0
- package/src/central/llm/chat.ts +133 -0
- package/src/central/registry.ts +162 -9
- package/src/central/speech/service.ts +9 -0
- package/src/central/spoke-ws.ts +13 -0
- package/src/central/store.ts +9 -12
- package/src/config.ts +30 -13
- package/src/index.ts +45 -43
- package/src/rpc.ts +33 -4
- package/src/spoke/concierge-agent.ts +1 -1
- package/src/spoke/conversation.ts +6 -75
- package/src/spoke/deliver.ts +18 -8
- package/src/spoke/hub-rpc.ts +7 -2
- package/src/spoke/hub-tool-subscriptions.ts +82 -0
- package/src/spoke/hub-tool-title.ts +89 -0
- package/src/spoke/hub-tool.ts +56 -18
- package/src/spoke/session-context.ts +10 -2
- package/src/spoke/spoke.ts +209 -238
- package/src/spoke/summary.ts +36 -1
- package/src/spoke/taskboard.ts +5 -6
- package/src/spoke/voice-front.ts +323 -30
- package/src/spoke/who-teams.ts +51 -2
- package/src/tui-messaging.ts +24 -10
- package/src/tui.ts +6 -6
- package/web/dist/assets/{ArtifactPage-BKISN-Qj.js → ArtifactPage-Bz992ZX6.js} +1 -1
- package/web/dist/assets/{ArtifactPane-CKOiAUNH.js → ArtifactPane-BJZNixJC.js} +1 -1
- package/web/dist/assets/ArtifactWorkbench-Dti3VP07.js +6 -0
- package/web/dist/assets/{Diagram-vdpmp3xu.css → Diagram-7y8kg3og.css} +1 -1
- package/web/dist/assets/Diagram-B4HdUxw0.js +1 -0
- package/web/dist/assets/{Library-CcjZXsfF.js → Library-CpzD2HDW.js} +2 -2
- package/web/dist/assets/Lightbox-BlbivCkd.js +1 -0
- package/web/dist/assets/MediaImage-Ch3ryIdR.js +4 -0
- package/web/dist/assets/ProfilesDestination-DlQeogea.js +1 -0
- package/web/dist/assets/{TeamsPage-CDyjrK-I.js → TeamsPage-4xdWCaI-.js} +1 -1
- package/web/dist/assets/{Watchtower-DYwoUWME.js → Watchtower-CpQdIRns.js} +2 -2
- package/web/dist/assets/{artifacts-DU9uRgs1.js → artifacts-But87Jfo.js} +1 -1
- package/web/dist/assets/index-BC0O1gfR.css +1 -0
- package/web/dist/assets/index-BS6lA6fN.js +33 -0
- package/web/dist/assets/{live-ycZ_aQZO.js → live-CVUFIdUX.js} +2 -2
- package/web/dist/assets/{pane-layout-0RrLHGDr.js → pane-layout-BW0RdX5a.js} +1 -1
- package/web/dist/assets/{renderer2d-BIwbgRoX.js → renderer2d-IaJiloPi.js} +1 -1
- package/web/dist/assets/{renderer3d-C1a7eYGQ.js → renderer3d-ZiD1uKGW.js} +1 -1
- package/web/dist/assets/{safe-area-DHhPy61Q.js → safe-area-C7IAlkgY.js} +1 -1
- package/web/dist/assets/{source-BWlvaODa.js → source-C-De8L3s.js} +1 -1
- package/web/dist/assets/toast-CXTwTvDw.js +9 -0
- package/web/dist/assets/vad-worklet-BfxJhrXy.js +27 -0
- package/web/dist/index.html +6 -6
- package/web/dist/assets/ArtifactWorkbench-d7R1o-rs.js +0 -6
- package/web/dist/assets/Diagram-azw2B_QH.js +0 -1
- package/web/dist/assets/Lightbox-Du56MXGX.js +0 -1
- package/web/dist/assets/MediaImage-Ds_JUx3a.js +0 -4
- package/web/dist/assets/ProfilesDestination-DdzbzmeK.js +0 -1
- package/web/dist/assets/index-C3ci5UtY.css +0 -1
- package/web/dist/assets/index-LNMZCqgE.js +0 -36
- package/web/dist/assets/toast-Cuu2K0hx.js +0 -1
- /package/{web/src/voice → packages/voice-client/src}/turn/LICENSE +0 -0
|
@@ -7,7 +7,7 @@ import { createInterface } from "readline";
|
|
|
7
7
|
// packages/cli/package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@huynle/hub-cli",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.10.0",
|
|
11
11
|
private: true,
|
|
12
12
|
description: "The hub CLI (`hub` / `hubctl`) for agents and scripts (internal; bundled into @huynle/hub, not published on its own).",
|
|
13
13
|
license: "MIT",
|
|
@@ -419,138 +419,6 @@ function parseAddress(addr) {
|
|
|
419
419
|
const scope = project ? { project } : {};
|
|
420
420
|
return role ? { kind: "role", role: match[1], ...scope } : { kind: "name", name: match[1], ...scope };
|
|
421
421
|
}
|
|
422
|
-
// packages/sdk/src/artifact-jobs.ts
|
|
423
|
-
var PATH = "/api/agent/artifacts";
|
|
424
|
-
var seg = (value) => encodeURIComponent(value);
|
|
425
|
-
var sig = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
426
|
-
function artifactJobsApi(hub) {
|
|
427
|
-
const jobs = (id) => `${PATH}/${seg(id)}/jobs`;
|
|
428
|
-
const job = (id, jobID, tail = "") => `${jobs(id)}/${seg(jobID)}${tail}`;
|
|
429
|
-
return {
|
|
430
|
-
create: async (artifactID, input, options = {}) => {
|
|
431
|
-
const response = await hub.request("POST", jobs(artifactID), { body: input, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig(options) });
|
|
432
|
-
const answer = await response.json();
|
|
433
|
-
return { job: answer.job, created: response.status === 201 };
|
|
434
|
-
},
|
|
435
|
-
list: (artifactID, options = {}) => hub.call("GET", jobs(artifactID), { query: { limit: options.limit, cursor: options.cursor }, ...sig(options) }),
|
|
436
|
-
get: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID), sig(options)),
|
|
437
|
-
context: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID, "/context"), sig(options)),
|
|
438
|
-
proposal: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID, "/proposal"), sig(options)),
|
|
439
|
-
submit: (artifactID, jobID, result, options) => hub.call("POST", job(artifactID, jobID, "/result"), { body: result, ...sig(options) }),
|
|
440
|
-
apply: (artifactID, jobID, expectedRevision, options) => hub.call("POST", job(artifactID, jobID, "/apply"), { body: { expectedRevision }, ...sig(options) }),
|
|
441
|
-
cancel: (artifactID, jobID, expectedRevision, options) => hub.call("POST", job(artifactID, jobID, "/cancel"), { body: { expectedRevision }, ...sig(options) })
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// packages/sdk/src/artifacts.ts
|
|
446
|
-
var PATH2 = "/api/agent/artifacts";
|
|
447
|
-
var seg2 = (value) => encodeURIComponent(value);
|
|
448
|
-
var sig2 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
449
|
-
function artifactsApi(hub) {
|
|
450
|
-
const publish = async (pathname, body, options = {}) => {
|
|
451
|
-
const response = await hub.request("POST", pathname, { body, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig2(options) });
|
|
452
|
-
const answer = await response.json();
|
|
453
|
-
return { artifact: answer.artifact, revision: answer.revision, created: response.status === 201 };
|
|
454
|
-
};
|
|
455
|
-
return {
|
|
456
|
-
list: (filter = {}) => hub.call("GET", PATH2, { query: { limit: filter.limit, cursor: filter.cursor, state: filter.state, workspace: filter.workspace }, ...sig2(filter) }),
|
|
457
|
-
get: (id, options) => hub.call("GET", `${PATH2}/${seg2(id)}`, sig2(options)),
|
|
458
|
-
create: (input, options) => publish(PATH2, input, options),
|
|
459
|
-
revise: (id, input, options) => publish(`${PATH2}/${seg2(id)}/revisions`, input, options),
|
|
460
|
-
revisions: (id, options = {}) => hub.call("GET", `${PATH2}/${seg2(id)}/revisions`, { query: { limit: options.limit, cursor: options.cursor }, ...sig2(options) }),
|
|
461
|
-
revision: (id, revisionID, options) => hub.call("GET", `${PATH2}/${seg2(id)}/revisions/${seg2(revisionID)}`, sig2(options)),
|
|
462
|
-
uploadBlob: async (body, mediaType, options = {}) => {
|
|
463
|
-
const response = await hub.request("POST", `${PATH2}/blobs`, { raw: { body, contentType: mediaType }, ...options.hash ? { headers: { "x-blob-hash": options.hash } } : {}, ...sig2(options) });
|
|
464
|
-
return await response.json();
|
|
465
|
-
},
|
|
466
|
-
download: (id, revisionID, hash, options) => hub.request("GET", `${PATH2}/${seg2(id)}/revisions/${seg2(revisionID)}/blobs/${seg2(hash)}`, sig2(options)),
|
|
467
|
-
update: (id, input, options) => hub.call("PATCH", `${PATH2}/${seg2(id)}`, { body: input, ...sig2(options) }),
|
|
468
|
-
setVisibility: (id, input, options) => hub.call("PUT", `${PATH2}/${seg2(id)}/visibility`, { body: input, ...sig2(options) }),
|
|
469
|
-
archive: (id, expectedRevision, options) => hub.call("POST", `${PATH2}/${seg2(id)}/archive`, { body: { expectedRevision }, ...sig2(options) }),
|
|
470
|
-
unarchive: (id, expectedRevision, options) => hub.call("POST", `${PATH2}/${seg2(id)}/unarchive`, { body: { expectedRevision }, ...sig2(options) }),
|
|
471
|
-
delete: async (id, expectedRevision, options) => {
|
|
472
|
-
await hub.call("DELETE", `${PATH2}/${seg2(id)}`, { body: { expectedRevision }, ...sig2(options) });
|
|
473
|
-
},
|
|
474
|
-
jobs: artifactJobsApi(hub)
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
// packages/sdk/src/team-intake.ts
|
|
478
|
-
var seg3 = (value) => encodeURIComponent(value);
|
|
479
|
-
var sig3 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
480
|
-
var path3 = (team) => `/api/agent/teams/${seg3(team)}/intake`;
|
|
481
|
-
function teamIntakeApi(hub) {
|
|
482
|
-
return {
|
|
483
|
-
submit: async (team, input, options = {}) => {
|
|
484
|
-
const response = await hub.request("POST", path3(team), { body: input, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig3(options) });
|
|
485
|
-
const answer = await response.json();
|
|
486
|
-
return { intake: answer.intake, created: response.status === 201 };
|
|
487
|
-
},
|
|
488
|
-
intake: (team, intakeID, options) => hub.call("GET", `${path3(team)}/${seg3(intakeID)}`, sig3(options)),
|
|
489
|
-
intakes: (team, filter = {}) => hub.call("GET", path3(team), { query: { status: filter.status, limit: filter.limit, cursor: filter.cursor }, ...sig3(filter) }),
|
|
490
|
-
setIntakeStatus: (team, intakeID, input, options) => hub.call("POST", `${path3(team)}/${seg3(intakeID)}/status`, { body: input, ...sig3(options) })
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
var TEAM_INTAKE_STATUS_INPUTS = ["open", "in_progress", "blocked", "done", "failed", "cancelled"];
|
|
494
|
-
async function reportIntakeStatus(api, team, intakeID, input, options = {}) {
|
|
495
|
-
const expectedRevision = input.expectedRevision ?? (await api.intake(team, intakeID, options)).intake.revision;
|
|
496
|
-
return api.setIntakeStatus(team, intakeID, { status: input.status, expectedRevision, ...input.reason !== undefined ? { reason: input.reason } : {} }, options);
|
|
497
|
-
}
|
|
498
|
-
// packages/sdk/src/teams.ts
|
|
499
|
-
var seg4 = (value) => encodeURIComponent(value);
|
|
500
|
-
var sig4 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
501
|
-
var key = (options = {}) => options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {};
|
|
502
|
-
var base = (team) => `/api/agent/teams/${seg4(team)}`;
|
|
503
|
-
function teamsApi(hub) {
|
|
504
|
-
const created = async (method, pathname, body, options = {}) => {
|
|
505
|
-
const response = await hub.request(method, pathname, { body, ...key(options), ...sig4(options) });
|
|
506
|
-
return { ...await response.json(), created: response.status === 201 };
|
|
507
|
-
};
|
|
508
|
-
const revised = (verb) => (team, expectedRevision, options) => hub.call("POST", `${base(team)}/${verb}`, { body: { expectedRevision }, ...sig4(options) });
|
|
509
|
-
return {
|
|
510
|
-
...teamIntakeApi(hub),
|
|
511
|
-
create: (spec, options) => created("POST", "/api/agent/teams", spec, options),
|
|
512
|
-
list: (filter = {}) => hub.call("GET", "/api/agent/teams", {
|
|
513
|
-
query: {
|
|
514
|
-
state: filter.state,
|
|
515
|
-
tag: filter.tags,
|
|
516
|
-
project: filter.project,
|
|
517
|
-
metadata: filter.metadata ? Object.entries(filter.metadata).map(([k, v]) => `${k}=${v}`) : undefined,
|
|
518
|
-
paused: filter.paused === undefined ? undefined : String(filter.paused),
|
|
519
|
-
limit: filter.limit,
|
|
520
|
-
cursor: filter.cursor
|
|
521
|
-
},
|
|
522
|
-
...sig4(filter)
|
|
523
|
-
}),
|
|
524
|
-
get: (team, options) => hub.call("GET", base(team), sig4(options)),
|
|
525
|
-
update: (team, patch, expectedRevision, options = {}) => hub.call("PATCH", base(team), { body: { ...patch, expectedRevision, ...options.publish ? { publish: true } : {} }, ...sig4(options) }),
|
|
526
|
-
draft: (team, options) => hub.call("GET", `${base(team)}/draft`, sig4(options)),
|
|
527
|
-
discardDraft: (team, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft`, { query: { expectedRevision }, ...sig4(options) }),
|
|
528
|
-
setRole: (team, role, expectedRevision, options) => {
|
|
529
|
-
const { name, ...fields } = role;
|
|
530
|
-
return hub.call("PUT", `${base(team)}/draft/roles/${seg4(name)}`, { body: { ...fields, expectedRevision }, ...sig4(options) });
|
|
531
|
-
},
|
|
532
|
-
removeRole: (team, role, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft/roles/${seg4(role)}`, { query: { expectedRevision }, ...sig4(options) }),
|
|
533
|
-
setEdge: (team, edge, expectedRevision, options) => hub.call("PUT", `${base(team)}/draft/edges`, { body: { ...edge, expectedRevision }, ...sig4(options) }),
|
|
534
|
-
removeEdge: (team, from, to, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft/edges`, { query: { from, to, expectedRevision }, ...sig4(options) }),
|
|
535
|
-
publish: (team, expectedRevision, options) => hub.call("POST", `${base(team)}/publish`, { body: { expectedRevision }, ...sig4(options) }),
|
|
536
|
-
pause: revised("pause"),
|
|
537
|
-
resume: revised("resume"),
|
|
538
|
-
archive: revised("archive"),
|
|
539
|
-
restore: revised("restore"),
|
|
540
|
-
versions: (team, options = {}) => hub.call("GET", `${base(team)}/versions`, { query: { limit: options.limit, cursor: options.cursor }, ...sig4(options) }),
|
|
541
|
-
version: (team, version, options) => hub.call("GET", `${base(team)}/versions/${version}`, sig4(options)),
|
|
542
|
-
diff: (team, options = {}) => hub.call("GET", `${base(team)}/diff`, { query: { from: options.from, to: options.to }, ...sig4(options) }),
|
|
543
|
-
staffing: (team, options = {}) => hub.call("GET", `${base(team)}/staffing`, { query: { ended: options.ended ? 1 : undefined }, ...sig4(options) }),
|
|
544
|
-
staff: (team, input, options) => created("PUT", `${base(team)}/staffing`, input, options),
|
|
545
|
-
launchMember: (team, input, options) => created("POST", `${base(team)}/staffing/launch`, input, options),
|
|
546
|
-
replace: (team, staffingID, input, options) => hub.call("POST", `${base(team)}/staffing/${seg4(staffingID)}/replace`, { body: input, ...sig4(options) }),
|
|
547
|
-
unstaff: (team, staffingID, expectedRevision, options) => hub.call("DELETE", `${base(team)}/staffing/${seg4(staffingID)}`, { query: { expectedRevision }, ...sig4(options) }),
|
|
548
|
-
roster: (team, options) => hub.call("GET", `${base(team)}/roster`, sig4(options)),
|
|
549
|
-
status: (team, options) => hub.call("GET", `${base(team)}/status`, sig4(options)),
|
|
550
|
-
settings: (options) => hub.call("GET", "/api/agent/team-settings", sig4(options)),
|
|
551
|
-
setSettings: (input, expectedRevision, options) => hub.call("PUT", "/api/agent/team-settings", { body: { teamIsolation: input.teamIsolation, expectedRevision }, ...sig4(options) })
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
422
|
// packages/sdk/src/errors.ts
|
|
555
423
|
class HubError extends Error {
|
|
556
424
|
status;
|
|
@@ -667,15 +535,288 @@ async function* sseEvents(response, signal) {
|
|
|
667
535
|
}
|
|
668
536
|
}
|
|
669
537
|
|
|
538
|
+
// packages/sdk/src/app-front.ts
|
|
539
|
+
var AGENT = "/api/agent";
|
|
540
|
+
var sig = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
541
|
+
var seg = (value) => encodeURIComponent(value).replace(/%40/g, "@");
|
|
542
|
+
var RESUMABLE = new Set(["slow", "token_expired"]);
|
|
543
|
+
function speechApi(hub) {
|
|
544
|
+
return {
|
|
545
|
+
async transcribe(audio, options = {}) {
|
|
546
|
+
const type = options.type ?? (audio instanceof Blob && audio.type ? audio.type : "audio/webm");
|
|
547
|
+
const response = await hub.request("POST", `${AGENT}/speech/transcribe`, { raw: { body: audio, contentType: type }, ...sig(options) });
|
|
548
|
+
return await response.json();
|
|
549
|
+
},
|
|
550
|
+
async speak(text, options = {}) {
|
|
551
|
+
const response = await hub.request("POST", `${AGENT}/speech/speak`, { body: { text }, ...sig(options) });
|
|
552
|
+
if (!response.body)
|
|
553
|
+
throw new HubTransportError("bad_response", "the hub sent no audio");
|
|
554
|
+
return response.body;
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function conversationApi(hub) {
|
|
559
|
+
const at = (addr, verb) => `${AGENT}/sessions/${seg(addr)}/${verb}`;
|
|
560
|
+
return {
|
|
561
|
+
set: (addr, on, options = {}) => hub.call("POST", at(addr, "conversation"), { body: options.front === undefined ? { on } : { on, front: options.front }, ...sig(options) }),
|
|
562
|
+
utterance: (addr, text, options = {}) => hub.call("POST", at(addr, "utterance"), { body: { text }, ...sig(options) }),
|
|
563
|
+
interrupt: async (addr, options = {}) => {
|
|
564
|
+
await hub.request("POST", at(addr, "interrupt"), sig(options));
|
|
565
|
+
},
|
|
566
|
+
stream: (addr, options = {}) => streamFrames(hub, at(addr, "stream"), options)
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
function appDecisionsApi(hub) {
|
|
570
|
+
return {
|
|
571
|
+
list: (options = {}) => hub.call("GET", `${AGENT}/decisions`, { query: { answerable: 1, state: options.state }, ...sig(options) }),
|
|
572
|
+
answer: (id, answer) => {
|
|
573
|
+
const { signal: _signal, ...body } = answer;
|
|
574
|
+
return hub.call("POST", `${AGENT}/decisions/${seg(id)}/answer`, { body, ...sig(answer) });
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function retryable(cause) {
|
|
579
|
+
if (cause instanceof HubError)
|
|
580
|
+
return cause.status === 429 || cause.status >= 500;
|
|
581
|
+
if (cause instanceof HubTransportError)
|
|
582
|
+
return cause.kind === "unreachable" || cause.kind === "stream" || cause.kind === "http" && (cause.status === undefined || cause.status === 429 || cause.status >= 500);
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
var wait = (ms, signal) => new Promise((resolve) => {
|
|
586
|
+
if (signal?.aborted)
|
|
587
|
+
return resolve();
|
|
588
|
+
const done = () => {
|
|
589
|
+
clearTimeout(timer);
|
|
590
|
+
signal?.removeEventListener("abort", done);
|
|
591
|
+
resolve();
|
|
592
|
+
};
|
|
593
|
+
const timer = setTimeout(done, ms);
|
|
594
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
595
|
+
});
|
|
596
|
+
async function* streamFrames(hub, pathname, options) {
|
|
597
|
+
const resume = options.resume ?? true;
|
|
598
|
+
const maxReconnects = options.maxReconnects ?? 5;
|
|
599
|
+
const base = options.reconnectDelayMs ?? 1000;
|
|
600
|
+
const cap = options.maxReconnectDelayMs ?? 30000;
|
|
601
|
+
let cursor = options.cursor;
|
|
602
|
+
let misses = 0;
|
|
603
|
+
let lastFailure;
|
|
604
|
+
let retryAfterMs = 0;
|
|
605
|
+
for (let attempt = 0;; attempt++) {
|
|
606
|
+
if (options.signal?.aborted)
|
|
607
|
+
return;
|
|
608
|
+
let response;
|
|
609
|
+
try {
|
|
610
|
+
response = await hub.request("GET", pathname, { headers: { accept: "text/event-stream", ...cursor ? { "last-event-id": cursor } : {} }, ...sig(options) });
|
|
611
|
+
} catch (cause) {
|
|
612
|
+
if (attempt === 0 || options.signal?.aborted || !retryable(cause))
|
|
613
|
+
throw cause;
|
|
614
|
+
lastFailure = cause;
|
|
615
|
+
retryAfterMs = cause instanceof HubError && cause.retryAfter !== undefined ? cause.retryAfter * 1000 : 0;
|
|
616
|
+
}
|
|
617
|
+
if (response) {
|
|
618
|
+
retryAfterMs = 0;
|
|
619
|
+
if (!response.body)
|
|
620
|
+
throw new HubTransportError("bad_response", "the hub sent no stream");
|
|
621
|
+
const reader = response.body.getReader();
|
|
622
|
+
const stop = () => void reader.cancel().catch(() => {});
|
|
623
|
+
options.signal?.addEventListener("abort", stop, { once: true });
|
|
624
|
+
const parser = new SseParser;
|
|
625
|
+
const decoder = new TextDecoder;
|
|
626
|
+
lastFailure = undefined;
|
|
627
|
+
try {
|
|
628
|
+
read:
|
|
629
|
+
for (;; ) {
|
|
630
|
+
let chunk;
|
|
631
|
+
try {
|
|
632
|
+
chunk = await reader.read();
|
|
633
|
+
} catch (cause) {
|
|
634
|
+
lastFailure = cause;
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
if (chunk.done || options.signal?.aborted)
|
|
638
|
+
break;
|
|
639
|
+
for (const event of parser.push(decoder.decode(chunk.value, { stream: true }))) {
|
|
640
|
+
if (event.id)
|
|
641
|
+
cursor = event.id;
|
|
642
|
+
if (event.event !== "message")
|
|
643
|
+
continue;
|
|
644
|
+
let frame;
|
|
645
|
+
try {
|
|
646
|
+
frame = JSON.parse(event.data);
|
|
647
|
+
} catch {
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
if (frame.type === "end") {
|
|
651
|
+
if (resume && RESUMABLE.has(frame.reason)) {
|
|
652
|
+
lastFailure = new HubTransportError("stream", `the stream ended (${frame.reason})`);
|
|
653
|
+
break read;
|
|
654
|
+
}
|
|
655
|
+
yield { frame };
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
if (frame.type !== "ready")
|
|
659
|
+
misses = 0;
|
|
660
|
+
yield cursor ? { frame, cursor } : { frame };
|
|
661
|
+
if (options.signal?.aborted)
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
} finally {
|
|
666
|
+
options.signal?.removeEventListener("abort", stop);
|
|
667
|
+
stop();
|
|
668
|
+
}
|
|
669
|
+
if (options.signal?.aborted || !resume)
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (++misses > maxReconnects) {
|
|
673
|
+
throw new HubTransportError("stream", `the conversation stream gave up after ${maxReconnects} reconnects${lastFailure instanceof Error ? ` (${lastFailure.message})` : ""}`, { cause: lastFailure });
|
|
674
|
+
}
|
|
675
|
+
const backoff = Math.min(cap, base * 2 ** (misses - 1));
|
|
676
|
+
await wait(Math.max(retryAfterMs, backoff * (0.5 + Math.random() * 0.5)), options.signal);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
// packages/sdk/src/artifact-jobs.ts
|
|
680
|
+
var PATH = "/api/agent/artifacts";
|
|
681
|
+
var seg2 = (value) => encodeURIComponent(value);
|
|
682
|
+
var sig2 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
683
|
+
function artifactJobsApi(hub) {
|
|
684
|
+
const jobs = (id) => `${PATH}/${seg2(id)}/jobs`;
|
|
685
|
+
const job = (id, jobID, tail = "") => `${jobs(id)}/${seg2(jobID)}${tail}`;
|
|
686
|
+
return {
|
|
687
|
+
create: async (artifactID, input, options = {}) => {
|
|
688
|
+
const response = await hub.request("POST", jobs(artifactID), { body: input, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig2(options) });
|
|
689
|
+
const answer = await response.json();
|
|
690
|
+
return { job: answer.job, created: response.status === 201 };
|
|
691
|
+
},
|
|
692
|
+
list: (artifactID, options = {}) => hub.call("GET", jobs(artifactID), { query: { limit: options.limit, cursor: options.cursor }, ...sig2(options) }),
|
|
693
|
+
get: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID), sig2(options)),
|
|
694
|
+
context: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID, "/context"), sig2(options)),
|
|
695
|
+
proposal: (artifactID, jobID, options) => hub.call("GET", job(artifactID, jobID, "/proposal"), sig2(options)),
|
|
696
|
+
submit: (artifactID, jobID, result, options) => hub.call("POST", job(artifactID, jobID, "/result"), { body: result, ...sig2(options) }),
|
|
697
|
+
apply: (artifactID, jobID, expectedRevision, options) => hub.call("POST", job(artifactID, jobID, "/apply"), { body: { expectedRevision }, ...sig2(options) }),
|
|
698
|
+
cancel: (artifactID, jobID, expectedRevision, options) => hub.call("POST", job(artifactID, jobID, "/cancel"), { body: { expectedRevision }, ...sig2(options) })
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// packages/sdk/src/artifacts.ts
|
|
703
|
+
var PATH2 = "/api/agent/artifacts";
|
|
704
|
+
var seg3 = (value) => encodeURIComponent(value);
|
|
705
|
+
var sig3 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
706
|
+
function artifactsApi(hub) {
|
|
707
|
+
const publish = async (pathname, body, options = {}) => {
|
|
708
|
+
const response = await hub.request("POST", pathname, { body, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig3(options) });
|
|
709
|
+
const answer = await response.json();
|
|
710
|
+
return { artifact: answer.artifact, revision: answer.revision, created: response.status === 201 };
|
|
711
|
+
};
|
|
712
|
+
return {
|
|
713
|
+
list: (filter = {}) => hub.call("GET", PATH2, { query: { limit: filter.limit, cursor: filter.cursor, state: filter.state, workspace: filter.workspace }, ...sig3(filter) }),
|
|
714
|
+
get: (id, options) => hub.call("GET", `${PATH2}/${seg3(id)}`, sig3(options)),
|
|
715
|
+
create: (input, options) => publish(PATH2, input, options),
|
|
716
|
+
revise: (id, input, options) => publish(`${PATH2}/${seg3(id)}/revisions`, input, options),
|
|
717
|
+
revisions: (id, options = {}) => hub.call("GET", `${PATH2}/${seg3(id)}/revisions`, { query: { limit: options.limit, cursor: options.cursor }, ...sig3(options) }),
|
|
718
|
+
revision: (id, revisionID, options) => hub.call("GET", `${PATH2}/${seg3(id)}/revisions/${seg3(revisionID)}`, sig3(options)),
|
|
719
|
+
uploadBlob: async (body, mediaType, options = {}) => {
|
|
720
|
+
const response = await hub.request("POST", `${PATH2}/blobs`, { raw: { body, contentType: mediaType }, ...options.hash ? { headers: { "x-blob-hash": options.hash } } : {}, ...sig3(options) });
|
|
721
|
+
return await response.json();
|
|
722
|
+
},
|
|
723
|
+
download: (id, revisionID, hash, options) => hub.request("GET", `${PATH2}/${seg3(id)}/revisions/${seg3(revisionID)}/blobs/${seg3(hash)}`, sig3(options)),
|
|
724
|
+
update: (id, input, options) => hub.call("PATCH", `${PATH2}/${seg3(id)}`, { body: input, ...sig3(options) }),
|
|
725
|
+
setVisibility: (id, input, options) => hub.call("PUT", `${PATH2}/${seg3(id)}/visibility`, { body: input, ...sig3(options) }),
|
|
726
|
+
archive: (id, expectedRevision, options) => hub.call("POST", `${PATH2}/${seg3(id)}/archive`, { body: { expectedRevision }, ...sig3(options) }),
|
|
727
|
+
unarchive: (id, expectedRevision, options) => hub.call("POST", `${PATH2}/${seg3(id)}/unarchive`, { body: { expectedRevision }, ...sig3(options) }),
|
|
728
|
+
delete: async (id, expectedRevision, options) => {
|
|
729
|
+
await hub.call("DELETE", `${PATH2}/${seg3(id)}`, { body: { expectedRevision }, ...sig3(options) });
|
|
730
|
+
},
|
|
731
|
+
jobs: artifactJobsApi(hub)
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
// packages/sdk/src/team-intake.ts
|
|
735
|
+
var seg4 = (value) => encodeURIComponent(value);
|
|
736
|
+
var sig4 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
737
|
+
var path3 = (team) => `/api/agent/teams/${seg4(team)}/intake`;
|
|
738
|
+
function teamIntakeApi(hub) {
|
|
739
|
+
return {
|
|
740
|
+
submit: async (team, input, options = {}) => {
|
|
741
|
+
const response = await hub.request("POST", path3(team), { body: input, ...options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {}, ...sig4(options) });
|
|
742
|
+
const answer = await response.json();
|
|
743
|
+
return { intake: answer.intake, created: response.status === 201 };
|
|
744
|
+
},
|
|
745
|
+
intake: (team, intakeID, options) => hub.call("GET", `${path3(team)}/${seg4(intakeID)}`, sig4(options)),
|
|
746
|
+
intakes: (team, filter = {}) => hub.call("GET", path3(team), { query: { status: filter.status, limit: filter.limit, cursor: filter.cursor }, ...sig4(filter) }),
|
|
747
|
+
setIntakeStatus: (team, intakeID, input, options) => hub.call("POST", `${path3(team)}/${seg4(intakeID)}/status`, { body: input, ...sig4(options) })
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
var TEAM_INTAKE_STATUS_INPUTS = ["open", "in_progress", "blocked", "done", "failed", "cancelled"];
|
|
751
|
+
async function reportIntakeStatus(api, team, intakeID, input, options = {}) {
|
|
752
|
+
const expectedRevision = input.expectedRevision ?? (await api.intake(team, intakeID, options)).intake.revision;
|
|
753
|
+
return api.setIntakeStatus(team, intakeID, { status: input.status, expectedRevision, ...input.reason !== undefined ? { reason: input.reason } : {} }, options);
|
|
754
|
+
}
|
|
755
|
+
// packages/sdk/src/teams.ts
|
|
756
|
+
var seg5 = (value) => encodeURIComponent(value);
|
|
757
|
+
var sig5 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
758
|
+
var key = (options = {}) => options.idempotencyKey ? { headers: { "idempotency-key": options.idempotencyKey } } : {};
|
|
759
|
+
var base = (team) => `/api/agent/teams/${seg5(team)}`;
|
|
760
|
+
function teamsApi(hub) {
|
|
761
|
+
const created = async (method, pathname, body, options = {}) => {
|
|
762
|
+
const response = await hub.request(method, pathname, { body, ...key(options), ...sig5(options) });
|
|
763
|
+
return { ...await response.json(), created: response.status === 201 };
|
|
764
|
+
};
|
|
765
|
+
const revised = (verb) => (team, expectedRevision, options) => hub.call("POST", `${base(team)}/${verb}`, { body: { expectedRevision }, ...sig5(options) });
|
|
766
|
+
return {
|
|
767
|
+
...teamIntakeApi(hub),
|
|
768
|
+
create: (spec, options) => created("POST", "/api/agent/teams", spec, options),
|
|
769
|
+
list: (filter = {}) => hub.call("GET", "/api/agent/teams", {
|
|
770
|
+
query: {
|
|
771
|
+
state: filter.state,
|
|
772
|
+
tag: filter.tags,
|
|
773
|
+
project: filter.project,
|
|
774
|
+
metadata: filter.metadata ? Object.entries(filter.metadata).map(([k, v]) => `${k}=${v}`) : undefined,
|
|
775
|
+
paused: filter.paused === undefined ? undefined : String(filter.paused),
|
|
776
|
+
limit: filter.limit,
|
|
777
|
+
cursor: filter.cursor
|
|
778
|
+
},
|
|
779
|
+
...sig5(filter)
|
|
780
|
+
}),
|
|
781
|
+
get: (team, options) => hub.call("GET", base(team), sig5(options)),
|
|
782
|
+
update: (team, patch, expectedRevision, options = {}) => hub.call("PATCH", base(team), { body: { ...patch, expectedRevision, ...options.publish ? { publish: true } : {} }, ...sig5(options) }),
|
|
783
|
+
draft: (team, options) => hub.call("GET", `${base(team)}/draft`, sig5(options)),
|
|
784
|
+
discardDraft: (team, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft`, { query: { expectedRevision }, ...sig5(options) }),
|
|
785
|
+
setRole: (team, role, expectedRevision, options) => {
|
|
786
|
+
const { name, ...fields } = role;
|
|
787
|
+
return hub.call("PUT", `${base(team)}/draft/roles/${seg5(name)}`, { body: { ...fields, expectedRevision }, ...sig5(options) });
|
|
788
|
+
},
|
|
789
|
+
removeRole: (team, role, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft/roles/${seg5(role)}`, { query: { expectedRevision }, ...sig5(options) }),
|
|
790
|
+
setEdge: (team, edge, expectedRevision, options) => hub.call("PUT", `${base(team)}/draft/edges`, { body: { ...edge, expectedRevision }, ...sig5(options) }),
|
|
791
|
+
removeEdge: (team, from, to, expectedRevision, options) => hub.call("DELETE", `${base(team)}/draft/edges`, { query: { from, to, expectedRevision }, ...sig5(options) }),
|
|
792
|
+
publish: (team, expectedRevision, options) => hub.call("POST", `${base(team)}/publish`, { body: { expectedRevision }, ...sig5(options) }),
|
|
793
|
+
pause: revised("pause"),
|
|
794
|
+
resume: revised("resume"),
|
|
795
|
+
archive: revised("archive"),
|
|
796
|
+
restore: revised("restore"),
|
|
797
|
+
versions: (team, options = {}) => hub.call("GET", `${base(team)}/versions`, { query: { limit: options.limit, cursor: options.cursor }, ...sig5(options) }),
|
|
798
|
+
version: (team, version, options) => hub.call("GET", `${base(team)}/versions/${version}`, sig5(options)),
|
|
799
|
+
diff: (team, options = {}) => hub.call("GET", `${base(team)}/diff`, { query: { from: options.from, to: options.to }, ...sig5(options) }),
|
|
800
|
+
staffing: (team, options = {}) => hub.call("GET", `${base(team)}/staffing`, { query: { ended: options.ended ? 1 : undefined }, ...sig5(options) }),
|
|
801
|
+
staff: (team, input, options) => created("PUT", `${base(team)}/staffing`, input, options),
|
|
802
|
+
launchMember: (team, input, options) => created("POST", `${base(team)}/staffing/launch`, input, options),
|
|
803
|
+
replace: (team, staffingID, input, options) => hub.call("POST", `${base(team)}/staffing/${seg5(staffingID)}/replace`, { body: input, ...sig5(options) }),
|
|
804
|
+
unstaff: (team, staffingID, expectedRevision, options) => hub.call("DELETE", `${base(team)}/staffing/${seg5(staffingID)}`, { query: { expectedRevision }, ...sig5(options) }),
|
|
805
|
+
roster: (team, options) => hub.call("GET", `${base(team)}/roster`, sig5(options)),
|
|
806
|
+
status: (team, options) => hub.call("GET", `${base(team)}/status`, sig5(options)),
|
|
807
|
+
settings: (options) => hub.call("GET", "/api/agent/team-settings", sig5(options)),
|
|
808
|
+
setSettings: (input, expectedRevision, options) => hub.call("PUT", "/api/agent/team-settings", { body: { teamIsolation: input.teamIsolation, expectedRevision }, ...sig5(options) })
|
|
809
|
+
};
|
|
810
|
+
}
|
|
670
811
|
// packages/sdk/src/concierge.ts
|
|
671
812
|
var WATCHLIST = "/api/agent/concierge/watchlist";
|
|
672
|
-
var
|
|
813
|
+
var sig6 = (options = {}) => options.signal ? { signal: options.signal } : {};
|
|
673
814
|
function conciergeApi(hub) {
|
|
674
|
-
const verb = (name) => (addr, options) => hub.call("POST", `${WATCHLIST}/${name}`, { body: { session: addr }, ...
|
|
815
|
+
const verb = (name) => (addr, options) => hub.call("POST", `${WATCHLIST}/${name}`, { body: { session: addr }, ...sig6(options) });
|
|
675
816
|
return {
|
|
676
817
|
watchlist: {
|
|
677
|
-
get: (options) => hub.call("GET", WATCHLIST,
|
|
678
|
-
update: (patch, expectedRevision, options) => hub.call("PUT", WATCHLIST, { body: { ...patch, expectedRevision }, ...
|
|
818
|
+
get: (options) => hub.call("GET", WATCHLIST, sig6(options)),
|
|
819
|
+
update: (patch, expectedRevision, options) => hub.call("PUT", WATCHLIST, { body: { ...patch, expectedRevision }, ...sig6(options) }),
|
|
679
820
|
watch: verb("watch"),
|
|
680
821
|
unwatch: verb("unwatch"),
|
|
681
822
|
mute: verb("mute"),
|
|
@@ -685,7 +826,7 @@ function conciergeApi(hub) {
|
|
|
685
826
|
}
|
|
686
827
|
|
|
687
828
|
// packages/sdk/src/client.ts
|
|
688
|
-
var
|
|
829
|
+
var AGENT2 = "/api/agent";
|
|
689
830
|
var WAIT_POLL_MAX_S = 60;
|
|
690
831
|
function queryString(query = {}) {
|
|
691
832
|
const params = new URLSearchParams;
|
|
@@ -724,69 +865,72 @@ class HubClient {
|
|
|
724
865
|
#fetch;
|
|
725
866
|
launches = {
|
|
726
867
|
create: async (spec, options = {}) => {
|
|
727
|
-
const response = await this.request("POST", `${
|
|
728
|
-
const body = await this.#json(response, `${
|
|
868
|
+
const response = await this.request("POST", `${AGENT2}/launches`, { body: spec, ...signalOf(options) });
|
|
869
|
+
const body = await this.#json(response, `${AGENT2}/launches`);
|
|
729
870
|
return { launch: body.launch, created: response.status === 201 };
|
|
730
871
|
},
|
|
731
872
|
list: (filter = {}) => {
|
|
732
873
|
const state = typeof filter.state === "string" ? filter.state : filter.state?.join(",");
|
|
733
|
-
return this.call("GET", `${
|
|
874
|
+
return this.call("GET", `${AGENT2}/launches`, { query: { state, label: filter.label }, ...signalOf(filter) });
|
|
734
875
|
},
|
|
735
|
-
get: (id, options = {}) => this.call("GET", `${
|
|
736
|
-
stop: (id, options = {}) => this.call("DELETE", `${
|
|
876
|
+
get: (id, options = {}) => this.call("GET", `${AGENT2}/launches/${segment(id)}`, signalOf(options)),
|
|
877
|
+
stop: (id, options = {}) => this.call("DELETE", `${AGENT2}/launches/${segment(id)}`, signalOf(options))
|
|
737
878
|
};
|
|
738
879
|
profiles = {
|
|
739
|
-
create: (input, options = {}) => this.call("POST", `${
|
|
740
|
-
import: (input, options = {}) => this.call("POST", `${
|
|
741
|
-
list: (filter = {}) => this.call("GET", `${
|
|
742
|
-
get: (id, options = {}) => this.call("GET", `${
|
|
743
|
-
update: (id, patch, options = {}) => this.call("PATCH", `${
|
|
744
|
-
usage: (id, options = {}) => this.call("GET", `${
|
|
745
|
-
versions: (id, options = {}) => this.call("GET", `${
|
|
746
|
-
createVersion: (id, input, options = {}) => this.call("POST", `${
|
|
747
|
-
version: (id, version, options = {}) => this.call("GET", `${
|
|
748
|
-
skill: (id, version, name, options = {}) => this.call("GET", `${
|
|
749
|
-
render: (id, version, name, params, options = {}) => this.call("POST", `${
|
|
750
|
-
ofSession: (addr, options = {}) => this.call("GET", `${
|
|
751
|
-
assign: (addr, input, options = {}) => this.call("PUT", `${
|
|
752
|
-
unassign: (addr, expectedRevision, options = {}) => this.call("DELETE", `${
|
|
753
|
-
sessionSkill: (addr, name, options = {}) => this.call("GET", `${
|
|
754
|
-
sessionRender: (addr, name, params, options = {}) => this.call("POST", `${
|
|
880
|
+
create: (input, options = {}) => this.call("POST", `${AGENT2}/profiles`, { body: input, ...idempotent(options) }),
|
|
881
|
+
import: (input, options = {}) => this.call("POST", `${AGENT2}/profiles/import`, { body: input, ...idempotent(options) }),
|
|
882
|
+
list: (filter = {}) => this.call("GET", `${AGENT2}/profiles`, { query: { state: filter.state, limit: filter.limit, cursor: filter.cursor, include: filter.include }, ...signalOf(filter) }),
|
|
883
|
+
get: (id, options = {}) => this.call("GET", `${AGENT2}/profiles/${segment(id)}`, signalOf(options)),
|
|
884
|
+
update: (id, patch, options = {}) => this.call("PATCH", `${AGENT2}/profiles/${segment(id)}`, { body: patch, ...signalOf(options) }),
|
|
885
|
+
usage: (id, options = {}) => this.call("GET", `${AGENT2}/profiles/${segment(id)}/usage`, { query: { limit: options.limit, cursor: options.cursor }, ...signalOf(options) }),
|
|
886
|
+
versions: (id, options = {}) => this.call("GET", `${AGENT2}/profiles/${segment(id)}/versions`, { query: { limit: options.limit, cursor: options.cursor }, ...signalOf(options) }),
|
|
887
|
+
createVersion: (id, input, options = {}) => this.call("POST", `${AGENT2}/profiles/${segment(id)}/versions`, { body: input, ...idempotent(options) }),
|
|
888
|
+
version: (id, version, options = {}) => this.call("GET", `${AGENT2}/profiles/${segment(id)}/versions/${version}`, signalOf(options)),
|
|
889
|
+
skill: (id, version, name, options = {}) => this.call("GET", `${AGENT2}/profiles/${segment(id)}/versions/${version}/skills/${segment(name)}`, signalOf(options)),
|
|
890
|
+
render: (id, version, name, params, options = {}) => this.call("POST", `${AGENT2}/profiles/${segment(id)}/versions/${version}/commands/${segment(name)}/render`, { body: { params }, ...signalOf(options) }),
|
|
891
|
+
ofSession: (addr, options = {}) => this.call("GET", `${AGENT2}/sessions/${segment(addr)}/profile`, signalOf(options)),
|
|
892
|
+
assign: (addr, input, options = {}) => this.call("PUT", `${AGENT2}/sessions/${segment(addr)}/profile`, { body: input, ...signalOf(options) }),
|
|
893
|
+
unassign: (addr, expectedRevision, options = {}) => this.call("DELETE", `${AGENT2}/sessions/${segment(addr)}/profile`, { query: { expectedRevision }, ...signalOf(options) }),
|
|
894
|
+
sessionSkill: (addr, name, options = {}) => this.call("GET", `${AGENT2}/sessions/${segment(addr)}/profile/skills/${segment(name)}`, signalOf(options)),
|
|
895
|
+
sessionRender: (addr, name, params, options = {}) => this.call("POST", `${AGENT2}/sessions/${segment(addr)}/profile/commands/${segment(name)}/render`, { body: { params }, ...signalOf(options) })
|
|
755
896
|
};
|
|
756
897
|
workspaces = {
|
|
757
|
-
create: (input, options = {}) => this.call("POST", `${
|
|
758
|
-
list: (filter = {}) => this.call("GET", `${
|
|
759
|
-
get: (id, options = {}) => this.call("GET", `${
|
|
760
|
-
update: (id, patch, options = {}) => this.call("PATCH", `${
|
|
761
|
-
archive: (id, expectedRevision, options = {}) => this.call("POST", `${
|
|
762
|
-
restore: (id, expectedRevision, options = {}) => this.call("POST", `${
|
|
763
|
-
bindings: (id, options = {}) => this.call("GET", `${
|
|
764
|
-
bind: (id, input, options = {}) => this.call("POST", `${
|
|
765
|
-
unbind: (id, bindingID, expectedRevision, options = {}) => this.call("DELETE", `${
|
|
766
|
-
members: (id, options = {}) => this.call("GET", `${
|
|
767
|
-
join: (id, input, options = {}) => this.call("POST", `${
|
|
768
|
-
setRole: (id, memberID, role, expectedRevision, options = {}) => this.call("PATCH", `${
|
|
769
|
-
leave: (id, memberID, expectedRevision, options = {}) => this.call("DELETE", `${
|
|
770
|
-
assignments: (id, filter = {}) => this.call("GET", `${
|
|
771
|
-
assignment: (id, assignmentID, options = {}) => this.call("GET", `${
|
|
772
|
-
assign: (id, input, options = {}) => this.call("POST", `${
|
|
773
|
-
setAssignmentStatus: (id, assignmentID, status, expectedRevision, options = {}) => this.call("PATCH", `${
|
|
774
|
-
reassign: (id, assignmentID, memberID, expectedRevision, options = {}) => this.call("PATCH", `${
|
|
775
|
-
supervision: (id, options = {}) => this.call("GET", `${
|
|
776
|
-
supervise: (id, input, options = {}) => this.call("PUT", `${
|
|
777
|
-
board: (id, options = {}) => this.call("GET", `${
|
|
778
|
-
master: (id, options = {}) => this.call("GET", `${
|
|
779
|
-
replaceMaster: (id, input, options = {}) => this.call("POST", `${
|
|
780
|
-
createSideChat: (id, input, options = {}) => this.call("POST", `${
|
|
781
|
-
sideChats: (id, filter = {}) => this.call("GET", `${
|
|
782
|
-
sideChat: (id, sideChatID, options = {}) => this.call("GET", `${
|
|
783
|
-
sideChatByID: (sideChatID, options = {}) => this.call("GET", `${
|
|
784
|
-
refreshSideChat: (id, sideChatID, expectedRevision, options = {}) => this.call("POST", `${
|
|
785
|
-
sendToMain: (id, sideChatID, text, options = {}) => this.call("POST", `${
|
|
898
|
+
create: (input, options = {}) => this.call("POST", `${AGENT2}/workspaces`, { body: input, ...idempotent(options) }),
|
|
899
|
+
list: (filter = {}) => this.call("GET", `${AGENT2}/workspaces`, { query: { state: filter.state, limit: filter.limit, cursor: filter.cursor }, ...signalOf(filter) }),
|
|
900
|
+
get: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}`, signalOf(options)),
|
|
901
|
+
update: (id, patch, options = {}) => this.call("PATCH", `${AGENT2}/workspaces/${segment(id)}`, { body: patch, ...signalOf(options) }),
|
|
902
|
+
archive: (id, expectedRevision, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/archive`, { body: { expectedRevision }, ...signalOf(options) }),
|
|
903
|
+
restore: (id, expectedRevision, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/restore`, { body: { expectedRevision }, ...signalOf(options) }),
|
|
904
|
+
bindings: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/bindings`, signalOf(options)),
|
|
905
|
+
bind: (id, input, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/bindings`, { body: input, ...idempotent(options) }),
|
|
906
|
+
unbind: (id, bindingID, expectedRevision, options = {}) => this.call("DELETE", `${AGENT2}/workspaces/${segment(id)}/bindings`, { query: { bindingID, expectedRevision }, ...signalOf(options) }),
|
|
907
|
+
members: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/members`, { query: { includeLeft: options.includeLeft ? 1 : undefined }, ...signalOf(options) }),
|
|
908
|
+
join: (id, input, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/members`, { body: input, ...idempotent(options) }),
|
|
909
|
+
setRole: (id, memberID, role, expectedRevision, options = {}) => this.call("PATCH", `${AGENT2}/workspaces/${segment(id)}/members/${segment(memberID)}`, { body: { role, expectedRevision }, ...signalOf(options) }),
|
|
910
|
+
leave: (id, memberID, expectedRevision, options = {}) => this.call("DELETE", `${AGENT2}/workspaces/${segment(id)}/members/${segment(memberID)}`, { query: { expectedRevision }, ...signalOf(options) }),
|
|
911
|
+
assignments: (id, filter = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/assignments`, { query: { memberID: filter.memberID, status: filter.status, limit: filter.limit, cursor: filter.cursor }, ...signalOf(filter) }),
|
|
912
|
+
assignment: (id, assignmentID, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/assignments/${segment(assignmentID)}`, signalOf(options)),
|
|
913
|
+
assign: (id, input, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/assignments`, { body: input, ...idempotent(options) }),
|
|
914
|
+
setAssignmentStatus: (id, assignmentID, status, expectedRevision, options = {}) => this.call("PATCH", `${AGENT2}/workspaces/${segment(id)}/assignments/${segment(assignmentID)}`, { body: { status, expectedRevision }, ...signalOf(options) }),
|
|
915
|
+
reassign: (id, assignmentID, memberID, expectedRevision, options = {}) => this.call("PATCH", `${AGENT2}/workspaces/${segment(id)}/assignments/${segment(assignmentID)}`, { body: { memberID, expectedRevision }, ...signalOf(options) }),
|
|
916
|
+
supervision: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/supervision`, signalOf(options)),
|
|
917
|
+
supervise: (id, input, options = {}) => this.call("PUT", `${AGENT2}/workspaces/${segment(id)}/supervision`, { body: input, ...signalOf(options) }),
|
|
918
|
+
board: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/board`, signalOf(options)),
|
|
919
|
+
master: (id, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/master`, signalOf(options)),
|
|
920
|
+
replaceMaster: (id, input, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/master`, { body: input, ...idempotent(options) }),
|
|
921
|
+
createSideChat: (id, input, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/side-chats`, { body: input, ...idempotent(options) }),
|
|
922
|
+
sideChats: (id, filter = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/side-chats`, { query: { limit: filter.limit, cursor: filter.cursor }, ...signalOf(filter) }),
|
|
923
|
+
sideChat: (id, sideChatID, options = {}) => this.call("GET", `${AGENT2}/workspaces/${segment(id)}/side-chats/${segment(sideChatID)}`, signalOf(options)),
|
|
924
|
+
sideChatByID: (sideChatID, options = {}) => this.call("GET", `${AGENT2}/side-chats/${segment(sideChatID)}`, signalOf(options)),
|
|
925
|
+
refreshSideChat: (id, sideChatID, expectedRevision, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/side-chats/${segment(sideChatID)}/refresh`, { body: { expectedRevision }, ...signalOf(options) }),
|
|
926
|
+
sendToMain: (id, sideChatID, text, options = {}) => this.call("POST", `${AGENT2}/workspaces/${segment(id)}/side-chats/${segment(sideChatID)}/send`, { body: { text, confirmed: true }, ...signalOf(options) })
|
|
786
927
|
};
|
|
787
928
|
artifacts = artifactsApi(this);
|
|
788
929
|
teams = teamsApi(this);
|
|
789
930
|
concierge = conciergeApi(this);
|
|
931
|
+
speech = speechApi(this);
|
|
932
|
+
conversation = conversationApi(this);
|
|
933
|
+
appDecisions = appDecisionsApi(this);
|
|
790
934
|
constructor(options) {
|
|
791
935
|
this.url = options.url;
|
|
792
936
|
this.#base = options.url.replace(/\/+$/, "");
|
|
@@ -795,7 +939,8 @@ class HubClient {
|
|
|
795
939
|
}
|
|
796
940
|
async request(method, pathname, options = {}) {
|
|
797
941
|
const target = `${pathname}${queryString(options.query)}`;
|
|
798
|
-
const
|
|
942
|
+
const token = typeof this.#token === "string" ? this.#token : await this.#token();
|
|
943
|
+
const headers = { ...options.headers, authorization: `Bearer ${token}`, accept: "application/json" };
|
|
799
944
|
if (options.body !== undefined)
|
|
800
945
|
headers["content-type"] = "application/json";
|
|
801
946
|
if (options.raw)
|
|
@@ -842,26 +987,26 @@ class HubClient {
|
|
|
842
987
|
}
|
|
843
988
|
}
|
|
844
989
|
whoami(options = {}) {
|
|
845
|
-
return this.call("GET", `${
|
|
990
|
+
return this.call("GET", `${AGENT2}/whoami`, signalOf(options));
|
|
846
991
|
}
|
|
847
992
|
status(options = {}) {
|
|
848
|
-
return this.call("GET", `${
|
|
993
|
+
return this.call("GET", `${AGENT2}/status`, signalOf(options));
|
|
849
994
|
}
|
|
850
995
|
sessions(filter = {}) {
|
|
851
996
|
const state = typeof filter.state === "string" ? filter.state : filter.state?.join(",");
|
|
852
|
-
return this.call("GET", `${
|
|
997
|
+
return this.call("GET", `${AGENT2}/sessions`, {
|
|
853
998
|
query: { project: filter.project, state, machine: filter.machine, label: filter.label, q: filter.q },
|
|
854
999
|
...signalOf(filter)
|
|
855
1000
|
});
|
|
856
1001
|
}
|
|
857
1002
|
show(addr, options = {}) {
|
|
858
|
-
return this.call("GET", `${
|
|
1003
|
+
return this.call("GET", `${AGENT2}/sessions/${segment(addr)}`, signalOf(options));
|
|
859
1004
|
}
|
|
860
1005
|
log(addr, options = {}) {
|
|
861
|
-
return this.call("GET", `${
|
|
1006
|
+
return this.call("GET", `${AGENT2}/sessions/${segment(addr)}/log`, { query: { n: options.n }, ...signalOf(options) });
|
|
862
1007
|
}
|
|
863
1008
|
who(options = {}) {
|
|
864
|
-
return this.call("GET", `${
|
|
1009
|
+
return this.call("GET", `${AGENT2}/who`, { query: { project: options.project, role: options.role === undefined ? undefined : bareRole(options.role), team: options.team }, ...signalOf(options) });
|
|
865
1010
|
}
|
|
866
1011
|
async* watch(options = {}) {
|
|
867
1012
|
const { signal } = options;
|
|
@@ -869,7 +1014,7 @@ class HubClient {
|
|
|
869
1014
|
return;
|
|
870
1015
|
let response;
|
|
871
1016
|
try {
|
|
872
|
-
response = await this.request("GET", `${
|
|
1017
|
+
response = await this.request("GET", `${AGENT2}/watch`, { query: { blocked: options.blocked ? "1" : undefined, session: options.session, cursor: options.cursor }, ...signalOf(options) });
|
|
873
1018
|
} catch (cause) {
|
|
874
1019
|
if (signal?.aborted)
|
|
875
1020
|
return;
|
|
@@ -878,49 +1023,61 @@ class HubClient {
|
|
|
878
1023
|
yield* sseEvents(response, signal);
|
|
879
1024
|
}
|
|
880
1025
|
events(options = {}) {
|
|
881
|
-
return this.call("GET", `${
|
|
1026
|
+
return this.call("GET", `${AGENT2}/events`, { query: { cursor: options.cursor, wait: options.wait, limit: options.limit, type: options.types, session: options.sessions }, ...signalOf(options) });
|
|
882
1027
|
}
|
|
883
1028
|
webhookCreate(input, options = {}) {
|
|
884
|
-
return this.call("POST", `${
|
|
1029
|
+
return this.call("POST", `${AGENT2}/webhooks`, { body: input, ...signalOf(options) });
|
|
885
1030
|
}
|
|
886
1031
|
webhooks(options = {}) {
|
|
887
|
-
return this.call("GET", `${
|
|
1032
|
+
return this.call("GET", `${AGENT2}/webhooks`, signalOf(options));
|
|
888
1033
|
}
|
|
889
1034
|
webhook(id, options = {}) {
|
|
890
|
-
return this.call("GET", `${
|
|
1035
|
+
return this.call("GET", `${AGENT2}/webhooks/${segment(id)}`, signalOf(options));
|
|
891
1036
|
}
|
|
892
1037
|
webhookDelete(id, options = {}) {
|
|
893
|
-
return this.call("DELETE", `${
|
|
1038
|
+
return this.call("DELETE", `${AGENT2}/webhooks/${segment(id)}`, signalOf(options));
|
|
1039
|
+
}
|
|
1040
|
+
subscribe(input, options = {}) {
|
|
1041
|
+
return this.call("POST", `${AGENT2}/subscriptions`, { body: input, ...signalOf(options) });
|
|
1042
|
+
}
|
|
1043
|
+
subscriptions(options = {}) {
|
|
1044
|
+
return this.call("GET", `${AGENT2}/subscriptions`, { query: { session: options.session }, ...signalOf(options) });
|
|
1045
|
+
}
|
|
1046
|
+
subscription(id, options = {}) {
|
|
1047
|
+
return this.call("GET", `${AGENT2}/subscriptions/${segment(id)}`, signalOf(options));
|
|
1048
|
+
}
|
|
1049
|
+
unsubscribe(id, options = {}) {
|
|
1050
|
+
return this.call("DELETE", `${AGENT2}/subscriptions/${segment(id)}`, signalOf(options));
|
|
894
1051
|
}
|
|
895
1052
|
setArchived(addr, archived, options = {}) {
|
|
896
|
-
return this.call("PUT", `${
|
|
1053
|
+
return this.call("PUT", `${AGENT2}/sessions/${segment(addr)}/archive`, { body: { archived }, ...signalOf(options) });
|
|
897
1054
|
}
|
|
898
1055
|
setPinned(addr, pinned, options = {}) {
|
|
899
|
-
return this.call("PUT", `${
|
|
1056
|
+
return this.call("PUT", `${AGENT2}/sessions/${segment(addr)}/pin`, { body: { pinned }, ...signalOf(options) });
|
|
900
1057
|
}
|
|
901
1058
|
intent(addr, options = {}) {
|
|
902
|
-
return this.call("GET", `${
|
|
1059
|
+
return this.call("GET", `${AGENT2}/sessions/${segment(addr)}/intent`, signalOf(options));
|
|
903
1060
|
}
|
|
904
1061
|
setIntent(addr, text, expectedRevision, options = {}) {
|
|
905
|
-
return this.call("PUT", `${
|
|
1062
|
+
return this.call("PUT", `${AGENT2}/sessions/${segment(addr)}/intent`, { body: { text, expectedRevision }, ...signalOf(options) });
|
|
906
1063
|
}
|
|
907
1064
|
previewArchiveInactive(inactiveFor, limit, options = {}) {
|
|
908
|
-
return this.call("POST", `${
|
|
1065
|
+
return this.call("POST", `${AGENT2}/sessions/archive-inactive`, { body: { preview: true, inactiveFor, limit }, ...signalOf(options) });
|
|
909
1066
|
}
|
|
910
1067
|
archiveInactive(previewToken, options = {}) {
|
|
911
|
-
return this.call("POST", `${
|
|
1068
|
+
return this.call("POST", `${AGENT2}/sessions/archive-inactive`, { body: { previewToken, confirm: true }, ...signalOf(options) });
|
|
912
1069
|
}
|
|
913
1070
|
name(name, options = {}) {
|
|
914
|
-
return this.call("POST", `${
|
|
1071
|
+
return this.call("POST", `${AGENT2}/name`, { body: { name, ...options.session ? { session: options.session } : {} }, ...signalOf(options) });
|
|
915
1072
|
}
|
|
916
1073
|
claimRole(role, options = {}) {
|
|
917
|
-
return this.call("POST", `${
|
|
1074
|
+
return this.call("POST", `${AGENT2}/roles/claim`, { body: { role: bareRole(role), ...options.exclusive ? { exclusive: true } : {}, ...roleTarget(options) }, ...signalOf(options) });
|
|
918
1075
|
}
|
|
919
1076
|
releaseRole(role, options = {}) {
|
|
920
|
-
return this.call("POST", `${
|
|
1077
|
+
return this.call("POST", `${AGENT2}/roles/release`, { body: { role: bareRole(role), ...roleTarget(options) }, ...signalOf(options) });
|
|
921
1078
|
}
|
|
922
1079
|
msg(to, text, options = {}) {
|
|
923
|
-
return this.call("POST", `${
|
|
1080
|
+
return this.call("POST", `${AGENT2}/msg`, { body: { to, text, ...sendFields(options), ...options.all ? { all: true } : {} }, ...idempotent(options) });
|
|
924
1081
|
}
|
|
925
1082
|
async ask(to, text, options = {}) {
|
|
926
1083
|
if (options.all && options.wait !== undefined)
|
|
@@ -937,7 +1094,7 @@ class HubClient {
|
|
|
937
1094
|
...options.wait !== undefined ? { wait: first } : {},
|
|
938
1095
|
...decisionFields(options)
|
|
939
1096
|
};
|
|
940
|
-
const asked = await this.call("POST", `${
|
|
1097
|
+
const asked = await this.call("POST", `${AGENT2}/ask`, { body, ...idempotent(options) });
|
|
941
1098
|
if ("sent" in asked)
|
|
942
1099
|
return asked;
|
|
943
1100
|
let current = asked;
|
|
@@ -949,28 +1106,28 @@ class HubClient {
|
|
|
949
1106
|
return current;
|
|
950
1107
|
}
|
|
951
1108
|
message(id, options = {}) {
|
|
952
|
-
return this.call("GET", `${
|
|
1109
|
+
return this.call("GET", `${AGENT2}/messages/${segment(id)}`, { query: { wait: options.wait }, ...signalOf(options) });
|
|
953
1110
|
}
|
|
954
1111
|
reply(id, text, options = {}) {
|
|
955
|
-
return this.call("POST", `${
|
|
1112
|
+
return this.call("POST", `${AGENT2}/reply`, { body: { replyTo: id, text, ...options.wake !== undefined ? { wake: options.wake } : {} }, ...signalOf(options) });
|
|
956
1113
|
}
|
|
957
1114
|
decline(id, why, options = {}) {
|
|
958
|
-
return this.call("POST", `${
|
|
1115
|
+
return this.call("POST", `${AGENT2}/decline`, { body: { replyTo: id, why }, ...signalOf(options) });
|
|
959
1116
|
}
|
|
960
1117
|
inbox(options = {}) {
|
|
961
|
-
return this.call("GET", `${
|
|
1118
|
+
return this.call("GET", `${AGENT2}/inbox`, signalOf(options));
|
|
962
1119
|
}
|
|
963
1120
|
mute(session, options = {}) {
|
|
964
|
-
return this.call("POST", `${
|
|
1121
|
+
return this.call("POST", `${AGENT2}/mute`, { body: { session }, ...signalOf(options) });
|
|
965
1122
|
}
|
|
966
1123
|
unmute(session, options = {}) {
|
|
967
|
-
return this.call("POST", `${
|
|
1124
|
+
return this.call("POST", `${AGENT2}/unmute`, { body: { session }, ...signalOf(options) });
|
|
968
1125
|
}
|
|
969
1126
|
decisions(options = {}) {
|
|
970
|
-
return this.call("GET", `${
|
|
1127
|
+
return this.call("GET", `${AGENT2}/decisions`, { query: { state: options.state }, ...signalOf(options) });
|
|
971
1128
|
}
|
|
972
1129
|
decision(id, options = {}) {
|
|
973
|
-
return this.call("GET", `${
|
|
1130
|
+
return this.call("GET", `${AGENT2}/decisions/${segment(id)}`, signalOf(options));
|
|
974
1131
|
}
|
|
975
1132
|
answerDecision(id, answer) {
|
|
976
1133
|
const { signal: _signal, ...body } = answer;
|
|
@@ -978,16 +1135,16 @@ class HubClient {
|
|
|
978
1135
|
}
|
|
979
1136
|
approve(addr, requestID, options = {}) {
|
|
980
1137
|
const body = { requestID, ...options.always ? { always: true } : {}, ...options.recommend ? { recommend: true } : {}, ...whyField(options) };
|
|
981
|
-
return this.call("POST", `${
|
|
1138
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/approve`, { body, ...signalOf(options) });
|
|
982
1139
|
}
|
|
983
1140
|
deny(addr, requestID, options = {}) {
|
|
984
|
-
return this.call("POST", `${
|
|
1141
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/deny`, { body: { requestID, ...whyField(options) }, ...signalOf(options) });
|
|
985
1142
|
}
|
|
986
1143
|
answer(addr, formID, answer, options = {}) {
|
|
987
|
-
return this.call("POST", `${
|
|
1144
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/answer`, { body: { formID, answer, ...whyField(options) }, ...signalOf(options) });
|
|
988
1145
|
}
|
|
989
1146
|
cancelForm(addr, formID, options = {}) {
|
|
990
|
-
return this.call("POST", `${
|
|
1147
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/answer`, { body: { formID, cancel: true, ...whyField(options) }, ...signalOf(options) });
|
|
991
1148
|
}
|
|
992
1149
|
prompt(addr, text, options = {}) {
|
|
993
1150
|
const body = {
|
|
@@ -997,38 +1154,38 @@ class HubClient {
|
|
|
997
1154
|
...options.wake !== undefined ? { wake: options.wake } : {},
|
|
998
1155
|
...whyField(options)
|
|
999
1156
|
};
|
|
1000
|
-
return this.call("POST", `${
|
|
1157
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/prompt`, { body, ...signalOf(options) });
|
|
1001
1158
|
}
|
|
1002
1159
|
stop(addr, options = {}) {
|
|
1003
|
-
return this.call("POST", `${
|
|
1160
|
+
return this.call("POST", `${AGENT2}/sessions/${segment(addr)}/stop`, { body: whyField(options), ...signalOf(options) });
|
|
1004
1161
|
}
|
|
1005
1162
|
grants(options = {}) {
|
|
1006
|
-
return this.call("GET", `${
|
|
1163
|
+
return this.call("GET", `${AGENT2}/grants`, signalOf(options));
|
|
1007
1164
|
}
|
|
1008
1165
|
grant(id, options = {}) {
|
|
1009
|
-
return this.call("GET", `${
|
|
1166
|
+
return this.call("GET", `${AGENT2}/grants/${segment(id)}`, signalOf(options));
|
|
1010
1167
|
}
|
|
1011
1168
|
createGrant(spec, options = {}) {
|
|
1012
|
-
return this.call("POST", `${
|
|
1169
|
+
return this.call("POST", `${AGENT2}/grants`, { body: spec, ...signalOf(options) });
|
|
1013
1170
|
}
|
|
1014
1171
|
updateGrant(id, spec, options = {}) {
|
|
1015
|
-
return this.call("PUT", `${
|
|
1172
|
+
return this.call("PUT", `${AGENT2}/grants/${segment(id)}`, { body: spec, ...signalOf(options) });
|
|
1016
1173
|
}
|
|
1017
1174
|
revokeGrant(id, options = {}) {
|
|
1018
|
-
return this.call("DELETE", `${
|
|
1175
|
+
return this.call("DELETE", `${AGENT2}/grants/${segment(id)}`, signalOf(options));
|
|
1019
1176
|
}
|
|
1020
1177
|
requestGrant(grant, why, options = {}) {
|
|
1021
|
-
return this.call("POST", `${
|
|
1178
|
+
return this.call("POST", `${AGENT2}/grants/requests`, { body: { grant, why }, ...signalOf(options) });
|
|
1022
1179
|
}
|
|
1023
1180
|
createAppToken(input = {}) {
|
|
1024
1181
|
const { signal: _signal, ...body } = input;
|
|
1025
|
-
return this.call("POST", `${
|
|
1182
|
+
return this.call("POST", `${AGENT2}/app-tokens`, { body, ...signalOf(input) });
|
|
1026
1183
|
}
|
|
1027
1184
|
appTokens(options = {}) {
|
|
1028
|
-
return this.call("GET", `${
|
|
1185
|
+
return this.call("GET", `${AGENT2}/app-tokens`, signalOf(options));
|
|
1029
1186
|
}
|
|
1030
1187
|
revokeAppToken(id, options = {}) {
|
|
1031
|
-
return this.call("DELETE", `${
|
|
1188
|
+
return this.call("DELETE", `${AGENT2}/app-tokens/${segment(id)}`, signalOf(options));
|
|
1032
1189
|
}
|
|
1033
1190
|
}
|
|
1034
1191
|
// packages/sdk/src/envelope.ts
|
|
@@ -1065,13 +1222,15 @@ function escapeBody(text) {
|
|
|
1065
1222
|
`).map((line) => FORGEABLE.test(line) ? `\\${line}` : line).join(`
|
|
1066
1223
|
`);
|
|
1067
1224
|
}
|
|
1225
|
+
var NOTICE_ONLY_APPS = new Set(["subscriptions"]);
|
|
1226
|
+
var noticeOnly = (from) => from.kind === "app" && NOTICE_ONLY_APPS.has(from.tokenID);
|
|
1068
1227
|
function renderEnvelope(input) {
|
|
1069
1228
|
const { id, kind } = input;
|
|
1070
1229
|
const to = sanitizeLabel(input.to);
|
|
1071
1230
|
const target = kind === "reply" || kind === "decline" ? `to you · re ${sanitizeLabel(input.replyTo ?? "")}` : to.startsWith("@@") ? `to ${to} → you` : "to you";
|
|
1072
1231
|
const header = `[hub] ${kind} from ${partyLabel(input.from)} ${target} · ${stamp(input.at)} · ${id}`;
|
|
1073
1232
|
const boundary = `----- ${id} -----`;
|
|
1074
|
-
const hint = kind === "ask" ? `↩ hub reply ${id} "…" · hub decline ${id} --why "…"${input.expiresAt === undefined ? "" : ` · expires ${stamp(input.expiresAt)}`}` : `↩ hub reply ${id} "…"`;
|
|
1233
|
+
const hint = noticeOnly(input.from) ? "↩ a notice: no reply needed (hub unsubscribe <sub_…> stops it)" : kind === "ask" ? `↩ hub reply ${id} "…" · hub decline ${id} --why "…"${input.expiresAt === undefined ? "" : ` · expires ${stamp(input.expiresAt)}`}` : `↩ hub reply ${id} "…"`;
|
|
1075
1234
|
return [header, boundary, escapeBody(input.text), boundary, hint].join(`
|
|
1076
1235
|
`);
|
|
1077
1236
|
}
|
|
@@ -3591,7 +3750,7 @@ function profileTemplateParts(template) {
|
|
|
3591
3750
|
|
|
3592
3751
|
// packages/protocol/src/concierge.ts
|
|
3593
3752
|
var SESSION_CONTEXT_FEATURE = "sessionContext";
|
|
3594
|
-
var SESSION_CONTEXT_KEYS = ["instructions", "board", "notes"];
|
|
3753
|
+
var SESSION_CONTEXT_KEYS = ["instructions", "board", "notes", "frontBoard"];
|
|
3595
3754
|
var SESSION_CONTEXT_LIMITS = { partChars: 40000, denyGlobs: 50, globChars: 100, allowTools: 50 };
|
|
3596
3755
|
var isRecord3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3597
3756
|
var TOOL_GLOB = /^[A-Za-z0-9_.*-]+$/;
|
|
@@ -4166,6 +4325,19 @@ var RECORDING_LIMITS = {
|
|
|
4166
4325
|
hubFlushMs: 2000,
|
|
4167
4326
|
hubFlushEvents: 100
|
|
4168
4327
|
};
|
|
4328
|
+
// packages/protocol/src/app-front.ts
|
|
4329
|
+
var ACCESS_TOKEN_TTL_MS = 60 * 60000;
|
|
4330
|
+
var REFRESH_TOKEN_IDLE_MS = 30 * 24 * 60 * 60000;
|
|
4331
|
+
var CONNECT_FLOW_TTL_MS = 10 * 60000;
|
|
4332
|
+
var APP_STREAM_LIMITS = {
|
|
4333
|
+
heartbeatMs: 20000,
|
|
4334
|
+
retryMs: 2000,
|
|
4335
|
+
recheckMs: 30000,
|
|
4336
|
+
bufferMaxBytes: 1 << 20,
|
|
4337
|
+
streamsPerApp: 4,
|
|
4338
|
+
streamsPerUser: 20
|
|
4339
|
+
};
|
|
4340
|
+
var LOOPBACK_HOSTS2 = new Set(["127.0.0.1", "[::1]", "localhost"]);
|
|
4169
4341
|
// packages/protocol/src/index.ts
|
|
4170
4342
|
var PROTOCOL_VERSION = 1;
|
|
4171
4343
|
var FORM_ANSWER_MAX_KEYS = 50;
|
|
@@ -4249,10 +4421,12 @@ var IMPLIED_OPENCODE_FEATURES = [
|
|
|
4249
4421
|
"expose",
|
|
4250
4422
|
"create"
|
|
4251
4423
|
];
|
|
4252
|
-
var OPTIONAL_SPOKE_FEATURES = [...IMPLIED_OPENCODE_FEATURES, "autoName", "sessionTokens", "deliver", "hubPrompt", "permissionMessage", "actTokens", "launch", "fork", "revert", "dismissError", "timelineMedia", PREVIEW_BUNDLE_FEATURE, "voiceFront"];
|
|
4424
|
+
var OPTIONAL_SPOKE_FEATURES = [...IMPLIED_OPENCODE_FEATURES, "autoName", "sessionTokens", "deliver", "hubPrompt", "permissionMessage", "actTokens", "launch", "fork", "revert", "dismissError", "timelineMedia", PREVIEW_BUNDLE_FEATURE, "voiceFront", "conciergeFront", "inboxCarried"];
|
|
4253
4425
|
var CORE_OPS = ["turn", "steer", "interrupt", "stop", "permission", "form"];
|
|
4254
4426
|
var KNOWN_SPOKE_FEATURES = [...CORE_OPS, ...OPTIONAL_SPOKE_FEATURES, "turnEvents", PROFILE_APPLY_FEATURE, SESSION_CONTEXT_FEATURE];
|
|
4255
4427
|
var SPOKE_FEATURES = [...OPTIONAL_SPOKE_FEATURES, PROFILE_APPLY_FEATURE, SESSION_CONTEXT_FEATURE];
|
|
4428
|
+
var RELAY_TEXT_MAX = 4000;
|
|
4429
|
+
var FRONT_UPDATE_MAX = 8000;
|
|
4256
4430
|
var SESSION_TOKENS_MAX = 500;
|
|
4257
4431
|
var SESSION_TOKEN_MAX_CHARS = 4096;
|
|
4258
4432
|
var MESSAGE_KINDS = ["msg", "ask", "reply", "decline", "primer", "decision", "prompt"];
|
|
@@ -4269,6 +4443,8 @@ function featureForOp(op) {
|
|
|
4269
4443
|
return "revert";
|
|
4270
4444
|
case "removeFront":
|
|
4271
4445
|
return "voiceFront";
|
|
4446
|
+
case "frontUpdate":
|
|
4447
|
+
return "conciergeFront";
|
|
4272
4448
|
default:
|
|
4273
4449
|
return op;
|
|
4274
4450
|
}
|
|
@@ -4359,6 +4535,9 @@ function isSpokeRequest(v) {
|
|
|
4359
4535
|
return nonEmpty(v.sessionID);
|
|
4360
4536
|
if (v.op === "openLink")
|
|
4361
4537
|
return (v.sessionID === undefined || nonEmpty(v.sessionID)) && (v.voice === undefined || typeof v.voice === "boolean");
|
|
4538
|
+
if (v.op === "relayToSession") {
|
|
4539
|
+
return nonEmpty(v.frontID) && v.frontID.length <= 300 && nonEmpty(v.session) && v.session.length <= 300 && str2(v.text) && v.text.trim().length > 0 && v.text.length <= RELAY_TEXT_MAX && (v.previous === undefined || typeof v.previous === "boolean") && (v.confirm === undefined || typeof v.confirm === "boolean");
|
|
4540
|
+
}
|
|
4362
4541
|
return false;
|
|
4363
4542
|
}
|
|
4364
4543
|
var PROMPT_IMAGE_MIMES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
@@ -4483,6 +4662,8 @@ function isServerRequest(v) {
|
|
|
4483
4662
|
case "dismissError":
|
|
4484
4663
|
case "removeFront":
|
|
4485
4664
|
return nonEmpty(v.sessionID);
|
|
4665
|
+
case "frontUpdate":
|
|
4666
|
+
return nonEmpty(v.sessionID) && str2(v.text) && v.text.trim().length > 0 && v.text.length <= FRONT_UPDATE_MAX && (v.finished === undefined || typeof v.finished === "boolean");
|
|
4486
4667
|
default:
|
|
4487
4668
|
return false;
|
|
4488
4669
|
}
|
|
@@ -4591,8 +4772,22 @@ var JOB_STATUSES = new Set(["running", "exited", "timeout", "killed"]);
|
|
|
4591
4772
|
var DEFAULT_LIST = Object.freeze({ days: 30, max: 100 });
|
|
4592
4773
|
var LIST_LIMITS = { days: 365, max: 500 };
|
|
4593
4774
|
var DEFAULT_SERVER = "http://127.0.0.1:4097";
|
|
4594
|
-
var
|
|
4595
|
-
var
|
|
4775
|
+
var OBSOLETE_CONFIG_KEYS = ["subagent", "workModel"];
|
|
4776
|
+
var OBSOLETE_WHY = {
|
|
4777
|
+
subagent: "the voice agent that delegated to it is gone",
|
|
4778
|
+
workModel: "the voice agent whose workers used it is gone"
|
|
4779
|
+
};
|
|
4780
|
+
var warnedKeys = new Set;
|
|
4781
|
+
function warnObsoleteKeys(raw, log = console.warn, seen = warnedKeys) {
|
|
4782
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
4783
|
+
return;
|
|
4784
|
+
for (const key of OBSOLETE_CONFIG_KEYS) {
|
|
4785
|
+
if (!(key in raw) || seen.has(key))
|
|
4786
|
+
continue;
|
|
4787
|
+
seen.add(key);
|
|
4788
|
+
log(`[hub] config.json: "${key}" is obsolete (${OBSOLETE_WHY[key]}: Voice mode always uses the voice front now); it is ignored and removed on the next save`);
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4596
4791
|
var MODEL_REF = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.:\/-]+(?:#[A-Za-z0-9_.-]+)?$/;
|
|
4597
4792
|
var modelRef = (v) => typeof v === "string" && v.length <= 200 && MODEL_REF.test(v) ? v : undefined;
|
|
4598
4793
|
function configPath(env = process.env, home = homedir()) {
|
|
@@ -4609,7 +4804,7 @@ function prepareConfigPath(env = process.env, home = homedir(), log) {
|
|
|
4609
4804
|
return file;
|
|
4610
4805
|
}
|
|
4611
4806
|
function defaults(machineName) {
|
|
4612
|
-
return { server: DEFAULT_SERVER, mode: "off", sessions: [], machineName,
|
|
4807
|
+
return { server: DEFAULT_SERVER, mode: "off", sessions: [], machineName, autoStartLocalHub: true, herdr: true, list: { ...DEFAULT_LIST } };
|
|
4613
4808
|
}
|
|
4614
4809
|
function normalize(raw, machineName) {
|
|
4615
4810
|
const base = defaults(machineName);
|
|
@@ -4624,12 +4819,10 @@ function normalize(raw, machineName) {
|
|
|
4624
4819
|
mode,
|
|
4625
4820
|
sessions,
|
|
4626
4821
|
machineName: typeof r.machineName === "string" && r.machineName ? r.machineName : machineName,
|
|
4627
|
-
subagent: typeof r.subagent === "string" && AGENT_ID.test(r.subagent) ? r.subagent : base.subagent,
|
|
4628
4822
|
autoStartLocalHub: r.autoStartLocalHub !== false,
|
|
4629
4823
|
herdr: r.herdr !== false,
|
|
4630
4824
|
list: listWindow(r.list),
|
|
4631
4825
|
...modelRef(r.voiceModel) ? { voiceModel: modelRef(r.voiceModel) } : {},
|
|
4632
|
-
...modelRef(r.workModel) ? { workModel: modelRef(r.workModel) } : {},
|
|
4633
4826
|
...typeof r.machineID === "string" && r.machineID ? { machineID: r.machineID } : {},
|
|
4634
4827
|
...typeof r.token === "string" && r.token ? { token: r.token } : {}
|
|
4635
4828
|
};
|
|
@@ -4644,7 +4837,9 @@ function listWindow(raw) {
|
|
|
4644
4837
|
}
|
|
4645
4838
|
function readConfig(file, machineName) {
|
|
4646
4839
|
try {
|
|
4647
|
-
|
|
4840
|
+
const raw = JSON.parse(readFileSync3(file, "utf8"));
|
|
4841
|
+
warnObsoleteKeys(raw);
|
|
4842
|
+
return normalize(raw, machineName);
|
|
4648
4843
|
} catch {
|
|
4649
4844
|
return defaults(machineName);
|
|
4650
4845
|
}
|
|
@@ -5721,7 +5916,7 @@ function normalizeDirectories(raw, field, problems, options) {
|
|
|
5721
5916
|
}
|
|
5722
5917
|
return out;
|
|
5723
5918
|
}
|
|
5724
|
-
var
|
|
5919
|
+
var LOOPBACK_HOSTS3 = new Set(["127.0.0.1", "[::1]", "localhost"]);
|
|
5725
5920
|
function loopbackOrigin(raw) {
|
|
5726
5921
|
if (typeof raw !== "string" || raw.length > 2048)
|
|
5727
5922
|
return;
|
|
@@ -5733,7 +5928,7 @@ function loopbackOrigin(raw) {
|
|
|
5733
5928
|
}
|
|
5734
5929
|
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
5735
5930
|
return;
|
|
5736
|
-
if (url.username || url.password || !
|
|
5931
|
+
if (url.username || url.password || !LOOPBACK_HOSTS3.has(url.hostname))
|
|
5737
5932
|
return;
|
|
5738
5933
|
if (url.pathname !== "/" && url.pathname !== "" || url.search || url.hash)
|
|
5739
5934
|
return;
|
|
@@ -9227,7 +9422,7 @@ import { arch as osArch, platform as osPlatform } from "node:os";
|
|
|
9227
9422
|
// packages/node/package.json
|
|
9228
9423
|
var package_default2 = {
|
|
9229
9424
|
name: "@huynle/hub-node",
|
|
9230
|
-
version: "0.
|
|
9425
|
+
version: "0.10.0",
|
|
9231
9426
|
private: true,
|
|
9232
9427
|
description: "`hub node`: the per-machine daemon that prepares, collects and cleans up launch workspaces (internal; shipped inside @huynle/hub, not published on its own).",
|
|
9233
9428
|
license: "MIT",
|
|
@@ -10682,7 +10877,7 @@ import path14 from "node:path";
|
|
|
10682
10877
|
// packages/runtime-openshell/package.json
|
|
10683
10878
|
var package_default3 = {
|
|
10684
10879
|
name: "@huynle/hub-runtime-openshell",
|
|
10685
|
-
version: "0.
|
|
10880
|
+
version: "0.10.0",
|
|
10686
10881
|
private: true,
|
|
10687
10882
|
description: "The `openshell` runtime of `hub node`: launches in NVIDIA OpenShell sandboxes, driven through the openshell CLI (internal; shipped inside @huynle/hub, not published on its own).",
|
|
10688
10883
|
license: "MIT",
|
|
@@ -12337,6 +12532,46 @@ function openShellCheckText(report) {
|
|
|
12337
12532
|
`);
|
|
12338
12533
|
}
|
|
12339
12534
|
|
|
12535
|
+
// packages/cli/src/subscriptions.ts
|
|
12536
|
+
var SUBSCRIBE_FLAGS = { type: "multi", delivery: "string", batch: "string", expires: "string", "max-per-hour": "string", subscriber: "string", note: "string" };
|
|
12537
|
+
var DELIVERIES2 = ["queue", "steer", "silent"];
|
|
12538
|
+
var safe2 = (v, max = 120) => sanitizeLabel(String(v), max);
|
|
12539
|
+
function subscribeInput(addrs, flags) {
|
|
12540
|
+
if (!addrs.length)
|
|
12541
|
+
throw new UsageError("needs at least one address (a session, @@role, #team or children)");
|
|
12542
|
+
const delivery = str(flags, "delivery");
|
|
12543
|
+
if (delivery !== undefined && !DELIVERIES2.includes(delivery))
|
|
12544
|
+
throw new UsageError(`--delivery is one of ${DELIVERIES2.join(", ")}`);
|
|
12545
|
+
const batch = str(flags, "batch");
|
|
12546
|
+
const expires = str(flags, "expires");
|
|
12547
|
+
const max = str(flags, "max-per-hour");
|
|
12548
|
+
if (max !== undefined && !/^\d+$/.test(max))
|
|
12549
|
+
throw new UsageError("--max-per-hour takes a whole number (1–120)");
|
|
12550
|
+
const types = flags.type;
|
|
12551
|
+
const subscriber = str(flags, "subscriber");
|
|
12552
|
+
const note = str(flags, "note");
|
|
12553
|
+
return {
|
|
12554
|
+
to: addrs.length === 1 ? addrs[0] : [...addrs],
|
|
12555
|
+
...types?.length ? { types: types.flatMap((t) => t.split(",")).map((t) => t.trim()).filter(Boolean) } : {},
|
|
12556
|
+
...delivery !== undefined ? { delivery } : {},
|
|
12557
|
+
...batch !== undefined ? { batch: durationArg(batch, "--batch") } : {},
|
|
12558
|
+
...expires !== undefined ? { expires: durationArg(expires, "--expires") } : {},
|
|
12559
|
+
...max !== undefined ? { maxPerHour: Number(max) } : {},
|
|
12560
|
+
...subscriber !== undefined ? { subscriber } : {},
|
|
12561
|
+
...note !== undefined ? { note } : {}
|
|
12562
|
+
};
|
|
12563
|
+
}
|
|
12564
|
+
var targets = (s) => s.targets.map((t) => t.kind === "children" ? "its subagents" : safe2(t.addr, 80)).join(", ");
|
|
12565
|
+
var iso4 = (ms) => new Date(ms).toISOString().slice(0, 16) + "Z";
|
|
12566
|
+
function subscriptionLine(s) {
|
|
12567
|
+
const extra = [safe2(s.delivery, 10), `batch ${Math.round(s.batchMs / 1000)}s`, `≤${s.maxPerHour}/h`, `expires ${iso4(s.expiresAt)}`, `${s.stats.delivered} delivered`, ...s.pending ? [`${s.pending} pending`] : [], ...s.stats.dropped ? [`${s.stats.dropped} dropped`] : [], ...s.stats.suppressed ? [`${s.stats.suppressed} loop-suppressed`] : []];
|
|
12568
|
+
return `${safe2(s.id, 40)} ${safe2(s.subscriber, 80)} ← ${targets(s)} [${s.types.map((t) => safe2(t, 40)).join(",")}] ${extra.join(" · ")}${s.note ? ` "${safe2(s.note, 200)}"` : ""}`;
|
|
12569
|
+
}
|
|
12570
|
+
var subscribedText = (b) => `subscribed ${subscriptionLine(b.subscription)}
|
|
12571
|
+
the subscriber gets one hub message per batch window; stop with \`hub unsubscribe ${safe2(b.subscription.id, 40)}\``;
|
|
12572
|
+
var subscriptionsText = (b) => b.subscriptions.length ? b.subscriptions.map(subscriptionLine).join(`
|
|
12573
|
+
`) : "no subscriptions";
|
|
12574
|
+
|
|
12340
12575
|
// packages/claude-code/src/main.ts
|
|
12341
12576
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
12342
12577
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
@@ -13022,7 +13257,7 @@ function buildHarnessHello(options) {
|
|
|
13022
13257
|
}
|
|
13023
13258
|
// packages/spoke-sdk/src/harness-spoke.ts
|
|
13024
13259
|
var INSPECT2 = Symbol.for("nodejs.util.inspect.custom");
|
|
13025
|
-
var MODIFIER_NEEDS = { permissionMessage: "permission", launch: "create", hubPrompt: "deliver", turnEvents: null };
|
|
13260
|
+
var MODIFIER_NEEDS = { permissionMessage: "permission", launch: "create", hubPrompt: "deliver", turnEvents: null, inboxCarried: null };
|
|
13026
13261
|
var ALWAYS = ["sessionTokens", "actTokens"];
|
|
13027
13262
|
var CORE2 = CORE_OPS;
|
|
13028
13263
|
|
|
@@ -13445,7 +13680,7 @@ var LINE_MAX = 16 * 1024 * 1024;
|
|
|
13445
13680
|
var STDERR_KEEP = 2000;
|
|
13446
13681
|
var record2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
|
|
13447
13682
|
var sleep6 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
13448
|
-
var
|
|
13683
|
+
var AGENT3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
13449
13684
|
var MODEL = /^[A-Za-z0-9][A-Za-z0-9._:@/\[\]-]{0,299}$/;
|
|
13450
13685
|
var PROVIDERS = new Set(["anthropic", "claude-code"]);
|
|
13451
13686
|
function launchDirectory(directory, roots) {
|
|
@@ -13475,7 +13710,7 @@ function launchDirectory(directory, roots) {
|
|
|
13475
13710
|
function launchAgent(agent) {
|
|
13476
13711
|
if (agent === undefined)
|
|
13477
13712
|
return;
|
|
13478
|
-
if (!
|
|
13713
|
+
if (!AGENT3.test(agent))
|
|
13479
13714
|
throw new Error(`Claude Code cannot take agent ${JSON.stringify(agent)} (letters, digits, ".", "_" and "-")`);
|
|
13480
13715
|
return agent;
|
|
13481
13716
|
}
|
|
@@ -14640,7 +14875,7 @@ import path23 from "node:path";
|
|
|
14640
14875
|
// packages/claude-code/package.json
|
|
14641
14876
|
var package_default4 = {
|
|
14642
14877
|
name: "@huynle/hub-claude-code",
|
|
14643
|
-
version: "0.
|
|
14878
|
+
version: "0.10.0",
|
|
14644
14879
|
private: true,
|
|
14645
14880
|
description: "The Claude Code hooks spoke: per-user daemon, hook bridge, plugin dir, `hub claude` wrapper and daemon-backed MCP server (internal; shipped inside @huynle/hub, not published on its own).",
|
|
14646
14881
|
license: "MIT",
|
|
@@ -14929,7 +15164,7 @@ import path26 from "node:path";
|
|
|
14929
15164
|
// packages/preset/package.json
|
|
14930
15165
|
var package_default5 = {
|
|
14931
15166
|
name: "@huynle/hub-preset",
|
|
14932
|
-
version: "0.
|
|
15167
|
+
version: "0.10.0",
|
|
14933
15168
|
private: true,
|
|
14934
15169
|
description: "The preset spoke: drives a harness without a spoke of its own through a terminal pane (tmux), described by a data-only preset; official presets in presets/ (internal; shipped inside @huynle/hub, not published on its own).",
|
|
14935
15170
|
license: "MIT",
|
|
@@ -15454,7 +15689,7 @@ import { openSync as openSync6, closeSync as closeSync6, readFileSync as readFil
|
|
|
15454
15689
|
// packages/codex/package.json
|
|
15455
15690
|
var package_default6 = {
|
|
15456
15691
|
name: "@huynle/hub-codex",
|
|
15457
|
-
version: "0.
|
|
15692
|
+
version: "0.10.0",
|
|
15458
15693
|
private: true,
|
|
15459
15694
|
description: "The Codex app-server spoke: attaches to Codex's app-server (its own over stdio, and the shared daemon's socket when present), and the `hub codex` wrapper (internal; shipped inside @huynle/hub, not published on its own).",
|
|
15460
15695
|
license: "MIT",
|
|
@@ -16026,7 +16261,7 @@ class CodexSessions {
|
|
|
16026
16261
|
const thread = this.#thread(req.sessionID);
|
|
16027
16262
|
if (thread.turnID)
|
|
16028
16263
|
throw new Error("The Codex session is busy (a turn is running); steer it instead");
|
|
16029
|
-
const turnID = await this.#startTurn(thread, input(req.text, req.images), "
|
|
16264
|
+
const turnID = await this.#startTurn(thread, input(req.text, req.images), "carried");
|
|
16030
16265
|
const end = await this.#waitTurn(thread, turnID);
|
|
16031
16266
|
const reply = thread.reply?.text ?? "";
|
|
16032
16267
|
if (!end)
|
|
@@ -16038,7 +16273,7 @@ class CodexSessions {
|
|
|
16038
16273
|
async steer(req) {
|
|
16039
16274
|
const thread = this.#thread(req.sessionID);
|
|
16040
16275
|
const id = inboxID();
|
|
16041
|
-
await this.#steerOrStart(thread, input(req.text, req.images), "
|
|
16276
|
+
await this.#steerOrStart(thread, input(req.text, req.images), "carried", id);
|
|
16042
16277
|
return { inboxID: id };
|
|
16043
16278
|
}
|
|
16044
16279
|
async interrupt(req) {
|
|
@@ -16224,7 +16459,9 @@ class CodexSessions {
|
|
|
16224
16459
|
const origin = clientID ? thread.inputs.get(clientID) : undefined;
|
|
16225
16460
|
if (clientID)
|
|
16226
16461
|
thread.inputs.delete(clientID);
|
|
16227
|
-
|
|
16462
|
+
const inboxID = plainID3(clientID && origin ? clientID : item.id);
|
|
16463
|
+
const data = origin === "hub" ? { origin: "hub" } : origin === "carried" ? { origin: "user", carried: true } : { origin: "user" };
|
|
16464
|
+
this.#emit({ type: "session.inbox.delivered", data: { sessionID: thread.hubID, inboxID, ...data } });
|
|
16228
16465
|
return;
|
|
16229
16466
|
}
|
|
16230
16467
|
if (!TOOL_ITEMS.has(item.type))
|
|
@@ -16610,7 +16847,7 @@ function startCodexSpoke(options) {
|
|
|
16610
16847
|
profileApply: profiles.handle
|
|
16611
16848
|
},
|
|
16612
16849
|
deliver: (req) => sessions.deliver(req),
|
|
16613
|
-
features: ["hubPrompt", "launch", "turnEvents"],
|
|
16850
|
+
features: ["hubPrompt", "launch", "turnEvents", "inboxCarried"],
|
|
16614
16851
|
onState: (state, error) => log(`hub connection ${state}${error ? `: ${error}` : ""}`),
|
|
16615
16852
|
...options.socket ? { socket: options.socket } : {},
|
|
16616
16853
|
...options.backoff ? { backoff: options.backoff } : {}
|
|
@@ -23277,7 +23514,7 @@ var PROVIDER_TIMEOUT_MS = 90000;
|
|
|
23277
23514
|
var MAX_OUTPUT3 = 1024 * 1024;
|
|
23278
23515
|
var VERSION_IN = /(?:^|[^0-9.])v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)(?![0-9A-Za-z.-])/;
|
|
23279
23516
|
var MODEL_LINE = /^[A-Za-z0-9][A-Za-z0-9._-]*\/\S+$/;
|
|
23280
|
-
var
|
|
23517
|
+
var safe3 = (detail) => isSecretValue(detail) ? "(details withheld: they looked like they carried a credential)" : detail.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
23281
23518
|
var errorText5 = (error) => error instanceof Error ? error.message : String(error);
|
|
23282
23519
|
async function runOnce(options, context, argv, timeoutMs) {
|
|
23283
23520
|
try {
|
|
@@ -23352,7 +23589,7 @@ async function verifyOpencode(context, options) {
|
|
|
23352
23589
|
results = [await versionProbe2(options, context), await providerProbe(options, context), await spokeProbe2(options, context)];
|
|
23353
23590
|
}
|
|
23354
23591
|
const observedAt = context.now();
|
|
23355
|
-
return { harness: "opencode", probes: results.map((p) => ({ ...p, observedAt, ...p.detail !== undefined ? { detail:
|
|
23592
|
+
return { harness: "opencode", probes: results.map((p) => ({ ...p, observedAt, ...p.detail !== undefined ? { detail: safe3(p.detail) } : {} })) };
|
|
23356
23593
|
}
|
|
23357
23594
|
function locateOpencodeBinary(probe) {
|
|
23358
23595
|
const snap = discover(probe, { now: 0 });
|
|
@@ -25999,7 +26236,7 @@ Reading
|
|
|
25999
26236
|
|
|
26000
26237
|
Identity
|
|
26001
26238
|
hub whoami who this credential is
|
|
26002
|
-
hub who [--project P] [--role R] [--team T] named and role-holding sessions (team members: their teams)
|
|
26239
|
+
hub who [--project P] [--role R] [--team T] online, named and role-holding sessions (team members: their teams)
|
|
26003
26240
|
hub name <@name> [--session <addr>]
|
|
26004
26241
|
hub intent <addr> [text… | --clear] what the session is for (one line, ≤ 280 characters, untrusted);
|
|
26005
26242
|
no text: show it (else its title); a session token sets only its own
|
|
@@ -26116,6 +26353,15 @@ Codex (app-server spoke)
|
|
|
26116
26353
|
hub codex-spoke install|uninstall [--dry-run] | status
|
|
26117
26354
|
the spoke service as a launchd agent / systemd user unit (printed, never loaded)
|
|
26118
26355
|
|
|
26356
|
+
Subscriptions (a session hears other sessions' events as batched hub messages; docs/subscriptions.md)
|
|
26357
|
+
hub subscribe <addr|@@role|#team|children>... [--type T]... [--delivery queue|steer|silent] [--batch 30s]
|
|
26358
|
+
[--expires 1d] [--max-per-hour N] [--subscriber <addr>] [--note "…"]
|
|
26359
|
+
types: state, state:idle, blocker, message, launch, naming, presence,
|
|
26360
|
+
manage, exact types or * (default state, blocker); in a session's shell it
|
|
26361
|
+
subscribes itself, a login names --subscriber (app tokens: events:subscribe)
|
|
26362
|
+
hub subscriptions [--session <addr>] yours (or what a session subscribes to and what follows it)
|
|
26363
|
+
hub unsubscribe <subID>
|
|
26364
|
+
|
|
26119
26365
|
Concierge watchlist (users; app tokens: sessions:read to show, sessions:manage to change)
|
|
26120
26366
|
hub watchlist [show] what the Concierge watches now, and why; its config and revision
|
|
26121
26367
|
hub watchlist watch|unwatch <addr> watch a session (a subagent: its root), or stop
|
|
@@ -26699,6 +26945,31 @@ ${openedText(body.decision)}` : outcome.text);
|
|
|
26699
26945
|
answer(context, body, (b) => watchlistVerbText("unmute", b));
|
|
26700
26946
|
}
|
|
26701
26947
|
},
|
|
26948
|
+
subscribe: {
|
|
26949
|
+
args: ["addr..."],
|
|
26950
|
+
flags: SUBSCRIBE_FLAGS,
|
|
26951
|
+
async handle(context) {
|
|
26952
|
+
const input = subscribeInput(context.parsed.args, context.parsed.flags);
|
|
26953
|
+
const body = await context.hub((hub) => hub.subscribe(input));
|
|
26954
|
+
answer(context, body, subscribedText);
|
|
26955
|
+
}
|
|
26956
|
+
},
|
|
26957
|
+
subscriptions: {
|
|
26958
|
+
flags: { session: "string" },
|
|
26959
|
+
async handle(context) {
|
|
26960
|
+
const session = str(context.parsed.flags, "session");
|
|
26961
|
+
const body = await context.hub((hub) => hub.subscriptions(session !== undefined ? { session } : {}));
|
|
26962
|
+
answer(context, body, subscriptionsText);
|
|
26963
|
+
}
|
|
26964
|
+
},
|
|
26965
|
+
unsubscribe: {
|
|
26966
|
+
args: ["<subID>"],
|
|
26967
|
+
async handle(context) {
|
|
26968
|
+
const id = context.parsed.args[0];
|
|
26969
|
+
await context.hub((hub) => hub.unsubscribe(id));
|
|
26970
|
+
answer(context, { removed: id }, () => `removed ${id}`);
|
|
26971
|
+
}
|
|
26972
|
+
},
|
|
26702
26973
|
logout: {
|
|
26703
26974
|
async handle(context) {
|
|
26704
26975
|
const file = loginFile(context.io.env, context.io.home);
|