@indigoai-us/hq-cli 5.345.190 → 5.345.193
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 +420 -0
- package/assets/bot-workers/setup/worker.yaml +91 -34
- package/dist/command-catalog.generated.d.ts +96 -19
- package/dist/command-catalog.generated.js +124 -21
- package/dist/commands/bot-jobs.d.ts +21 -18
- package/dist/commands/bot-jobs.js +127 -39
- package/dist/commands/bot.d.ts +7 -4
- package/dist/commands/bot.js +289 -140
- package/dist/commands/core-jobs-schedule.js +10 -0
- package/dist/commands/daemon.js +37 -0
- package/dist/commands/files.d.ts +41 -6
- package/dist/commands/files.js +108 -27
- package/dist/commands/pack-start-bot.d.ts +4 -6
- package/dist/commands/pack-start-bot.js +4 -8
- package/dist/commands/signals-run.d.ts +45 -0
- package/dist/commands/signals-run.js +175 -0
- package/dist/commands/signals.d.ts +1 -0
- package/dist/commands/signals.js +3 -0
- package/dist/commands/sources.d.ts +11 -0
- package/dist/commands/sources.js +137 -25
- package/dist/commands/staff/reset-test-account.d.ts +10 -0
- package/dist/commands/staff/reset-test-account.js +18 -2
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +31171 -52512
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/bot/api.d.ts +3 -2
- package/dist/lib/bot/config.d.ts +2 -0
- package/dist/lib/bot/fleet-cron.d.ts +121 -0
- package/dist/lib/bot/fleet-cron.js +319 -0
- package/dist/lib/bot/fleet-local.d.ts +113 -2
- package/dist/lib/bot/fleet-local.js +597 -35
- package/dist/lib/bot/fleet-owner-companies.d.ts +12 -0
- package/dist/lib/bot/fleet-owner-companies.js +30 -0
- package/dist/lib/bot/fleet-watch.d.ts +25 -0
- package/dist/lib/bot/fleet-watch.js +51 -0
- package/dist/lib/bot/index.d.ts +1 -1
- package/dist/lib/bot/index.js +1 -1
- package/dist/lib/bot/job-run.d.ts +5 -4
- package/dist/lib/bot/job-run.js +5 -4
- package/dist/lib/bot/jobs/hot-signal-sync.d.ts +57 -3
- package/dist/lib/bot/jobs/hot-signal-sync.js +163 -4
- package/dist/lib/bot/local-jobs.d.ts +13 -2
- package/dist/lib/bot/local-jobs.js +17 -4
- package/dist/lib/bot/progress.d.ts +14 -0
- package/dist/lib/bot/progress.js +47 -1
- package/dist/lib/bot/run.d.ts +55 -2
- package/dist/lib/bot/run.js +192 -10
- package/dist/lib/bot/setup-tool-offer.d.ts +1 -0
- package/dist/lib/bot/setup-tool-offer.js +16 -0
- package/dist/lib/bot/signals-engine-flag.d.ts +18 -0
- package/dist/lib/bot/signals-engine-flag.js +30 -0
- package/dist/lib/daemon/catalog.d.ts +4 -0
- package/dist/lib/daemon/catalog.js +29 -9
- package/dist/lib/daemon/legacy.d.ts +6 -0
- package/dist/lib/daemon/legacy.js +16 -10
- package/dist/lib/daemon/run.d.ts +1 -0
- package/dist/lib/daemon/run.js +10 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/flag-registry.d.ts +13 -1
- package/dist/lib/flag-registry.js +46 -0
- package/dist/lib/hot-channels/adapters/attio.d.ts +75 -2
- package/dist/lib/hot-channels/adapters/attio.js +367 -29
- package/dist/lib/hot-channels/adapters/gmail.d.ts +14 -0
- package/dist/lib/hot-channels/adapters/gmail.js +59 -2
- package/dist/lib/hot-channels/adapters/linear.d.ts +24 -0
- package/dist/lib/hot-channels/adapters/linear.js +71 -1
- package/dist/lib/hot-channels/adapters/meetings.js +4 -1
- package/dist/lib/hot-channels/adapters/slack.js +7 -3
- package/dist/lib/hot-channels/alert.js +1 -1
- package/dist/lib/hot-channels/contract.d.ts +11 -0
- package/dist/lib/hot-channels/contract.js +1 -0
- package/dist/lib/hot-channels/cursors.js +1 -1
- package/dist/lib/hot-channels/landing.d.ts +6 -2
- package/dist/lib/hot-channels/landing.js +13 -6
- package/dist/lib/hot-channels/ledger.js +2 -0
- package/dist/lib/hot-channels/loop.js +18 -4
- package/dist/lib/hot-channels/registry.js +9 -1
- package/dist/lib/hot-channels/run.d.ts +18 -0
- package/dist/lib/hot-channels/run.js +15 -4
- package/dist/lib/hot-channels/signals-pass.d.ts +1 -0
- package/dist/lib/hot-channels/signals-pass.js +7 -5
- package/dist/lib/hot-channels/sync-lock.js +22 -6
- package/dist/lib/mesh/live/daemon/install.d.ts +22 -0
- package/dist/lib/mesh/live/daemon/install.js +117 -30
- package/dist/lib/signals/adapters-catalog.d.ts +77 -0
- package/dist/lib/signals/adapters-catalog.js +194 -0
- package/dist/lib/signals/engine.d.ts +196 -0
- package/dist/lib/signals/engine.js +495 -0
- package/dist/lib/signals/failure-alert.d.ts +89 -0
- package/dist/lib/signals/failure-alert.js +175 -0
- package/dist/lib/signals/local-date.d.ts +3 -0
- package/dist/lib/signals/local-date.js +6 -0
- package/dist/lib/signals/projection.d.ts +42 -0
- package/dist/lib/signals/projection.js +67 -0
- package/dist/lib/signals/reply.d.ts +112 -0
- package/dist/lib/signals/reply.js +368 -0
- package/dist/lib/signals/run-lock.d.ts +36 -0
- package/dist/lib/signals/run-lock.js +148 -0
- package/dist/lib/signals/run-record.d.ts +24 -0
- package/dist/lib/signals/run-record.js +82 -0
- package/dist/lib/signals/sanitize.d.ts +105 -0
- package/dist/lib/signals/sanitize.js +439 -0
- package/dist/lib/signals/settings.d.ts +10 -0
- package/dist/lib/signals/settings.js +48 -0
- package/dist/lib/signals/steps/adapters.d.ts +14 -0
- package/dist/lib/signals/steps/adapters.js +156 -0
- package/dist/lib/signals/steps/entity-similarity.d.ts +10 -0
- package/dist/lib/signals/steps/entity-similarity.js +47 -0
- package/dist/lib/signals/steps/extract.d.ts +113 -0
- package/dist/lib/signals/steps/extract.js +765 -0
- package/dist/lib/signals/steps/garden.d.ts +24 -0
- package/dist/lib/signals/steps/garden.js +250 -0
- package/dist/lib/signals/steps/types.d.ts +112 -0
- package/dist/lib/signals/steps/types.js +4 -0
- package/dist/lib/signals/steps/upload.d.ts +43 -0
- package/dist/lib/signals/steps/upload.js +324 -0
- package/dist/lib/signals/write-guard.d.ts +63 -0
- package/dist/lib/signals/write-guard.js +287 -0
- package/dist/utils/resident-package-preload.js +16 -0
- package/package.json +9 -9
- package/dist/lib/bot/fleet-default-flag.d.ts +0 -31
- package/dist/lib/bot/fleet-default-flag.js +0 -127
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"hq-cli-daemon-sync-runner","type":"module","version":"6.18.
|
|
1
|
+
{"name":"hq-cli-daemon-sync-runner","type":"module","version":"6.18.108","bundleSha256":"b908c99715d125c651043d1a67e0549d7b05e9d6f7ab42b6963b60789df1f2ba","formatVersion":1}
|
package/dist/lib/bot/api.d.ts
CHANGED
|
@@ -39,8 +39,9 @@ export interface InboxItem {
|
|
|
39
39
|
memberCount?: number;
|
|
40
40
|
senderTrust?: "member";
|
|
41
41
|
/**
|
|
42
|
-
* Scheduled-job run items only (channel === "job").
|
|
43
|
-
*
|
|
42
|
+
* Scheduled-job run items only (channel === "job"). A local bot's own loop
|
|
43
|
+
* builds them from its jobs.json (lib/bot/local-jobs.ts); for a hosted agent
|
|
44
|
+
* the cloud fires the job and writes this durable item. The run carries its own
|
|
44
45
|
* prompt instead of `text` (server: hq-pro-agents jobs/run-record.ts
|
|
45
46
|
* `JobRunInboxItem`).
|
|
46
47
|
*/
|
package/dist/lib/bot/config.d.ts
CHANGED
|
@@ -93,6 +93,8 @@ export interface BotConfig {
|
|
|
93
93
|
engine?: BotEngineMetadata;
|
|
94
94
|
fleetAuthPending?: boolean;
|
|
95
95
|
fleetServiceInstallPending?: boolean;
|
|
96
|
+
/** A newer HQ Fleet Local release is installed for this bot; the gateway restarts once the bot is idle. */
|
|
97
|
+
fleetRestartPending?: boolean;
|
|
96
98
|
/**
|
|
97
99
|
* "personal" (acts as its owner everywhere) or "company" (acts as itself,
|
|
98
100
|
* member of `companies`). Missing on bots created before kinds existed:
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { type BotConfig } from "./config.js";
|
|
2
|
+
import { type FleetLocalControlDeps } from "./fleet-local.js";
|
|
3
|
+
export interface FleetCronSchedule {
|
|
4
|
+
kind?: string;
|
|
5
|
+
expr?: string;
|
|
6
|
+
minutes?: number;
|
|
7
|
+
run_at?: string;
|
|
8
|
+
display?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface FleetCronJob {
|
|
11
|
+
id: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
prompt?: string;
|
|
14
|
+
script?: string | null;
|
|
15
|
+
no_agent?: boolean;
|
|
16
|
+
schedule?: FleetCronSchedule;
|
|
17
|
+
schedule_display?: string;
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
state?: string;
|
|
20
|
+
created_at?: string;
|
|
21
|
+
next_run_at?: string | null;
|
|
22
|
+
last_run_at?: string | null;
|
|
23
|
+
last_status?: string | null;
|
|
24
|
+
repeat?: {
|
|
25
|
+
times?: number | null;
|
|
26
|
+
completed?: number;
|
|
27
|
+
};
|
|
28
|
+
deliver?: string;
|
|
29
|
+
origin?: Record<string, unknown> | null;
|
|
30
|
+
workdir?: string | null;
|
|
31
|
+
fire_claim?: unknown;
|
|
32
|
+
}
|
|
33
|
+
export interface FleetCronOrigin {
|
|
34
|
+
platform: "hqdm";
|
|
35
|
+
chat_id: string;
|
|
36
|
+
user_id: string;
|
|
37
|
+
chat_name?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface FleetCronCreateInput {
|
|
40
|
+
prompt: string;
|
|
41
|
+
schedule: string;
|
|
42
|
+
origin: FleetCronOrigin;
|
|
43
|
+
name?: string;
|
|
44
|
+
script?: string;
|
|
45
|
+
noAgent?: boolean;
|
|
46
|
+
workdir?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface FleetCronOps {
|
|
49
|
+
list(): FleetCronJob[];
|
|
50
|
+
create(input: FleetCronCreateInput): FleetCronJob;
|
|
51
|
+
remove(id: string): boolean;
|
|
52
|
+
reschedule(id: string, schedule: string): FleetCronJob | null;
|
|
53
|
+
}
|
|
54
|
+
export type FleetCronRunner = (executable: string, args: string[], options: Record<string, unknown>) => Buffer | string;
|
|
55
|
+
export interface FleetCronDeps extends Pick<FleetLocalControlDeps, "fleetHome" | "platform"> {
|
|
56
|
+
run?: FleetCronRunner;
|
|
57
|
+
env?: NodeJS.ProcessEnv;
|
|
58
|
+
}
|
|
59
|
+
export declare const FLEET_CRON_BRIDGE: string;
|
|
60
|
+
export declare function runFleetCronRequest(agentUid: string, request: Record<string, unknown>, deps?: FleetCronDeps): unknown;
|
|
61
|
+
export declare function fleetCronOps(agentUid: string, deps?: FleetCronDeps): FleetCronOps;
|
|
62
|
+
export declare function fleetOwnerOrigin(ownerUid: string, jobs?: readonly FleetCronJob[]): FleetCronOrigin;
|
|
63
|
+
export declare function fleetScheduleFromLegacy(expr: string): string;
|
|
64
|
+
export interface FleetJobsMigrationResult {
|
|
65
|
+
imported: number;
|
|
66
|
+
alreadyPresent: number;
|
|
67
|
+
skipped: string[];
|
|
68
|
+
/** Where the old list went. Null when some jobs could not move: jobs.json then stays. */
|
|
69
|
+
renamedTo: string | null;
|
|
70
|
+
}
|
|
71
|
+
export declare function migrateLegacyJobsToFleet(dir: string, config: Pick<BotConfig, "ownerUid" | "hqRoot">, ops: FleetCronOps, now?: Date): FleetJobsMigrationResult | null;
|
|
72
|
+
export declare const FLEET_HOT_SIGNAL_SYNC_NAME = "hot-signal-sync";
|
|
73
|
+
export declare const FLEET_HOT_SIGNAL_SYNC_SCHEDULE = "30 6 * * *";
|
|
74
|
+
export declare function fleetHotSignalSyncScript(company: string): string;
|
|
75
|
+
export declare function companyOfHotSignalSyncJob(job: FleetCronJob): string | null;
|
|
76
|
+
export declare function renderFleetHotSignalSyncScript(input: {
|
|
77
|
+
nodeBinary: string;
|
|
78
|
+
hqBinary: string;
|
|
79
|
+
company: string;
|
|
80
|
+
hqRoot: string;
|
|
81
|
+
logFile: string;
|
|
82
|
+
/**
|
|
83
|
+
* cli.bot-signals-engine-job. On (the default here): the script runs the
|
|
84
|
+
* signals engine. Off: it runs the plain hot-channel sync (`hq sources sync`),
|
|
85
|
+
* the job these bots ran before the engine.
|
|
86
|
+
*/
|
|
87
|
+
signalsEngine?: boolean;
|
|
88
|
+
}): string;
|
|
89
|
+
export interface EnsureFleetHotSignalSyncInput {
|
|
90
|
+
dir: string;
|
|
91
|
+
config: Pick<BotConfig, "ownerUid" | "hqRoot" | "companySlug" | "kind" | "companies" | "workerId">;
|
|
92
|
+
ops: FleetCronOps;
|
|
93
|
+
profileDir: string;
|
|
94
|
+
activeCompany: string | null;
|
|
95
|
+
ownerCompanies?: readonly string[];
|
|
96
|
+
otherBotDirs: readonly string[];
|
|
97
|
+
nodeBinary: string;
|
|
98
|
+
hqBinary: string;
|
|
99
|
+
/**
|
|
100
|
+
* cli.bot-signals-engine-job (default off). Every company still gets the
|
|
101
|
+
* daily 06:30 hot-signal-sync job; the flag picks what its script runs: the
|
|
102
|
+
* signals engine when true, the plain hot-channel sync when false. The script
|
|
103
|
+
* is rewritten on every call, so flipping the flag takes effect on the next
|
|
104
|
+
* bot start without re-registering the job.
|
|
105
|
+
*/
|
|
106
|
+
signalsJobEnabled: boolean;
|
|
107
|
+
now?: Date;
|
|
108
|
+
}
|
|
109
|
+
export interface FleetHotSignalSyncCompanyResult {
|
|
110
|
+
company: string;
|
|
111
|
+
created: boolean;
|
|
112
|
+
job: FleetCronJob | null;
|
|
113
|
+
heldBy?: string;
|
|
114
|
+
}
|
|
115
|
+
export interface EnsureFleetHotSignalSyncResult {
|
|
116
|
+
companies: FleetHotSignalSyncCompanyResult[];
|
|
117
|
+
removed: string[];
|
|
118
|
+
}
|
|
119
|
+
export declare function fleetHotSignalSyncCompanies(config: EnsureFleetHotSignalSyncInput["config"], activeCompany: string | null, ownerCompanies?: readonly string[]): string[];
|
|
120
|
+
export declare function ensureFleetHotSignalSync(input: EnsureFleetHotSignalSyncInput): EnsureFleetHotSignalSyncResult;
|
|
121
|
+
//# sourceMappingURL=fleet-cron.d.ts.map
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { effectiveBotCompanies, effectiveBotKind } from "./config.js";
|
|
5
|
+
import { fleetLocalRuntimePython, stderrTail } from "./fleet-local.js";
|
|
6
|
+
import { readLocalJobs, withJobsLock, writeLocalJobs } from "./local-jobs.js";
|
|
7
|
+
import { currentHotSignalSyncCompany, forgetHotSignalSyncRegistrationsExcept, hotSignalSyncJobCompany, fleetHotSignalSyncRegistered, markFleetHotSignalSyncRegistered, otherBotWithHotSignalSync, } from "./jobs/hot-signal-sync.js";
|
|
8
|
+
const RESULT_MARKER = "@@HQ_FLEET_CRON@@";
|
|
9
|
+
export const FLEET_CRON_BRIDGE = [
|
|
10
|
+
"import json, os, sys",
|
|
11
|
+
"sys.path.insert(0, sys.argv[1])",
|
|
12
|
+
"request = json.loads(sys.stdin.read())",
|
|
13
|
+
"def emit(value):",
|
|
14
|
+
` sys.stdout.write("\\n${RESULT_MARKER}" + json.dumps(value, default=str) + "\\n")`,
|
|
15
|
+
"try:",
|
|
16
|
+
" from cron import jobs as cron_jobs",
|
|
17
|
+
" with cron_jobs.use_cron_store(os.environ['HQ_FLEET_HOME']):",
|
|
18
|
+
" op = request.get('op')",
|
|
19
|
+
" if op == 'list':",
|
|
20
|
+
" result = cron_jobs.list_jobs(include_disabled=True)",
|
|
21
|
+
" elif op == 'create':",
|
|
22
|
+
" result = cron_jobs.create_job(**request['job'])",
|
|
23
|
+
" elif op == 'remove':",
|
|
24
|
+
" result = cron_jobs.remove_job(request['id'])",
|
|
25
|
+
" elif op == 'reschedule':",
|
|
26
|
+
" result = cron_jobs.update_job(request['id'], {'schedule': request['schedule']})",
|
|
27
|
+
" else:",
|
|
28
|
+
" raise ValueError('unknown operation ' + str(op))",
|
|
29
|
+
" emit({'ok': True, 'result': result})",
|
|
30
|
+
"except Exception as exc:",
|
|
31
|
+
" emit({'ok': False, 'error': str(exc), 'type': type(exc).__name__})",
|
|
32
|
+
].join("\n");
|
|
33
|
+
function expectedError(message) {
|
|
34
|
+
return Object.assign(new Error(message), { expected: true });
|
|
35
|
+
}
|
|
36
|
+
export function runFleetCronRequest(agentUid, request, deps = {}) {
|
|
37
|
+
const runtime = fleetLocalRuntimePython(agentUid, deps);
|
|
38
|
+
const run = deps.run ?? execFileSync;
|
|
39
|
+
let output;
|
|
40
|
+
try {
|
|
41
|
+
output = run(runtime.python, ["-I", "-c", FLEET_CRON_BRIDGE, runtime.source], {
|
|
42
|
+
input: JSON.stringify(request),
|
|
43
|
+
encoding: "utf8",
|
|
44
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
45
|
+
env: { ...(deps.env ?? process.env), HQ_FLEET_HOME: runtime.profileDir, HQ_FLEET_ENABLE_PROJECT_PLUGINS: "0" },
|
|
46
|
+
timeout: 60_000,
|
|
47
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
48
|
+
windowsHide: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const tail = stderrTail(error);
|
|
53
|
+
throw expectedError(`The HQ Fleet Runtime could not open the bot's scheduled jobs.${tail ? `\n${tail}` : ""}`);
|
|
54
|
+
}
|
|
55
|
+
const text = Buffer.isBuffer(output) ? output.toString("utf8") : output;
|
|
56
|
+
const line = text.split(/\r?\n/).reverse().find((entry) => entry.startsWith(RESULT_MARKER));
|
|
57
|
+
if (!line)
|
|
58
|
+
throw expectedError("The HQ Fleet Runtime returned no answer about the bot's scheduled jobs.");
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(line.slice(RESULT_MARKER.length));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw expectedError("The HQ Fleet Runtime returned an unreadable answer about the bot's scheduled jobs.");
|
|
65
|
+
}
|
|
66
|
+
if (parsed.ok !== true) {
|
|
67
|
+
throw expectedError(typeof parsed.error === "string" && parsed.error ? parsed.error : "The HQ Fleet Runtime refused the change.");
|
|
68
|
+
}
|
|
69
|
+
return parsed.result;
|
|
70
|
+
}
|
|
71
|
+
function asJob(value) {
|
|
72
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
73
|
+
return null;
|
|
74
|
+
const record = value;
|
|
75
|
+
return typeof record.id === "string" && record.id ? record : null;
|
|
76
|
+
}
|
|
77
|
+
export function fleetCronOps(agentUid, deps = {}) {
|
|
78
|
+
return {
|
|
79
|
+
list() {
|
|
80
|
+
const result = runFleetCronRequest(agentUid, { op: "list" }, deps);
|
|
81
|
+
return Array.isArray(result) ? result.map(asJob).filter((job) => job !== null) : [];
|
|
82
|
+
},
|
|
83
|
+
create(input) {
|
|
84
|
+
const job = asJob(runFleetCronRequest(agentUid, {
|
|
85
|
+
op: "create",
|
|
86
|
+
job: {
|
|
87
|
+
prompt: input.prompt,
|
|
88
|
+
schedule: input.schedule,
|
|
89
|
+
deliver: "origin",
|
|
90
|
+
origin: input.origin,
|
|
91
|
+
...(input.name ? { name: input.name } : {}),
|
|
92
|
+
...(input.script ? { script: input.script } : {}),
|
|
93
|
+
...(input.noAgent ? { no_agent: true } : {}),
|
|
94
|
+
...(input.workdir ? { workdir: input.workdir } : {}),
|
|
95
|
+
},
|
|
96
|
+
}, deps));
|
|
97
|
+
if (!job)
|
|
98
|
+
throw expectedError("The HQ Fleet Runtime did not return the new job.");
|
|
99
|
+
return job;
|
|
100
|
+
},
|
|
101
|
+
remove(id) {
|
|
102
|
+
return runFleetCronRequest(agentUid, { op: "remove", id }, deps) === true;
|
|
103
|
+
},
|
|
104
|
+
reschedule(id, schedule) {
|
|
105
|
+
return asJob(runFleetCronRequest(agentUid, { op: "reschedule", id, schedule }, deps));
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export function fleetOwnerOrigin(ownerUid, jobs = []) {
|
|
110
|
+
const known = jobs
|
|
111
|
+
.map((job) => job.origin)
|
|
112
|
+
.find((origin) => origin && origin.platform === "hqdm" && origin.chat_id === ownerUid && typeof origin.chat_name === "string" && origin.chat_name);
|
|
113
|
+
return {
|
|
114
|
+
platform: "hqdm",
|
|
115
|
+
chat_id: ownerUid,
|
|
116
|
+
user_id: ownerUid,
|
|
117
|
+
...(known ? { chat_name: known.chat_name } : {}),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function throwSchedule(message) {
|
|
121
|
+
throw Object.assign(new Error(message), { expected: true });
|
|
122
|
+
}
|
|
123
|
+
function unshiftDayOfWeekTerm(term) {
|
|
124
|
+
const step = term.match(/^(.+)\/(\d+)$/);
|
|
125
|
+
if (step)
|
|
126
|
+
return `${unshiftDayOfWeekTerm(step[1])}/${step[2]}`;
|
|
127
|
+
if (term === "*")
|
|
128
|
+
return term;
|
|
129
|
+
const range = term.match(/^(\d+)-(\d+)$/);
|
|
130
|
+
if (range)
|
|
131
|
+
return `${Number(range[1]) - 1}-${Number(range[2]) - 1}`;
|
|
132
|
+
if (/^\d+$/.test(term))
|
|
133
|
+
return String(Number(term) - 1);
|
|
134
|
+
return term;
|
|
135
|
+
}
|
|
136
|
+
export function fleetScheduleFromLegacy(expr) {
|
|
137
|
+
const trimmed = expr.trim();
|
|
138
|
+
const rate = trimmed.match(/^rate\(\s*(\d+)\s+(minute|minutes|hour|hours|day|days)\s*\)$/i);
|
|
139
|
+
if (rate)
|
|
140
|
+
return `every ${rate[1]}${rate[2].toLowerCase()[0]}`;
|
|
141
|
+
const cron = trimmed.match(/^cron\(\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*\)$/i);
|
|
142
|
+
if (!cron)
|
|
143
|
+
throwSchedule(`"${trimmed}" is not a schedule the HQ Fleet Runtime can run.`);
|
|
144
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek, year] = cron.slice(1);
|
|
145
|
+
if (year !== "*")
|
|
146
|
+
throwSchedule(`"${trimmed}" names a year; the HQ Fleet Runtime runs recurring schedules only.`);
|
|
147
|
+
const dom = dayOfMonth === "?" ? "*" : dayOfMonth;
|
|
148
|
+
const dow = dayOfWeek === "?" ? "*" : dayOfWeek.split(",").map((term) => unshiftDayOfWeekTerm(term.trim())).join(",");
|
|
149
|
+
return `${minute} ${hour} ${dom} ${month} ${dow}`;
|
|
150
|
+
}
|
|
151
|
+
function migratedJobsPath(dir, now) {
|
|
152
|
+
const first = path.join(dir, "jobs.migrated.json");
|
|
153
|
+
if (!fs.existsSync(first))
|
|
154
|
+
return first;
|
|
155
|
+
return path.join(dir, `jobs.migrated-${now.toISOString().replace(/[:.]/g, "-")}.json`);
|
|
156
|
+
}
|
|
157
|
+
export function migrateLegacyJobsToFleet(dir, config, ops, now = new Date()) {
|
|
158
|
+
const file = path.join(dir, "jobs.json");
|
|
159
|
+
if (!fs.existsSync(file))
|
|
160
|
+
return null;
|
|
161
|
+
return withJobsLock(dir, () => {
|
|
162
|
+
const legacy = readLocalJobs(dir).filter((job) => hotSignalSyncJobCompany(job.context) === null);
|
|
163
|
+
if (legacy.length === 0)
|
|
164
|
+
return null;
|
|
165
|
+
const existing = ops.list();
|
|
166
|
+
const origin = fleetOwnerOrigin(config.ownerUid, existing);
|
|
167
|
+
let imported = 0;
|
|
168
|
+
let alreadyPresent = 0;
|
|
169
|
+
const skipped = [];
|
|
170
|
+
const moved = new Set();
|
|
171
|
+
for (const job of legacy) {
|
|
172
|
+
let schedule;
|
|
173
|
+
try {
|
|
174
|
+
schedule = /^(cron|rate)\(/i.test(job.cron.trim()) ? fleetScheduleFromLegacy(job.cron) : job.cron.trim();
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
skipped.push(job.jobId);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const present = existing.some((candidate) => candidate.prompt === job.prompt && candidate.schedule?.expr === schedule);
|
|
181
|
+
if (present) {
|
|
182
|
+
alreadyPresent += 1;
|
|
183
|
+
moved.add(job.jobId);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
existing.push(ops.create({ prompt: job.prompt, schedule, origin, workdir: config.hqRoot }));
|
|
187
|
+
imported += 1;
|
|
188
|
+
moved.add(job.jobId);
|
|
189
|
+
}
|
|
190
|
+
if (skipped.length > 0) {
|
|
191
|
+
// Some jobs could not move. jobs.json stays, with the jobs that could not
|
|
192
|
+
// move left in it; only the jobs now in the Fleet schedule leave it.
|
|
193
|
+
if (moved.size > 0) {
|
|
194
|
+
const all = readLocalJobs(dir);
|
|
195
|
+
writeLocalJobs(dir, all.filter((job) => !moved.has(job.jobId)));
|
|
196
|
+
}
|
|
197
|
+
return { imported, alreadyPresent, skipped, renamedTo: null };
|
|
198
|
+
}
|
|
199
|
+
const renamedTo = migratedJobsPath(dir, now);
|
|
200
|
+
fs.renameSync(file, renamedTo);
|
|
201
|
+
return { imported, alreadyPresent, skipped, renamedTo };
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
export const FLEET_HOT_SIGNAL_SYNC_NAME = "hot-signal-sync";
|
|
205
|
+
export const FLEET_HOT_SIGNAL_SYNC_SCHEDULE = "30 6 * * *";
|
|
206
|
+
export function fleetHotSignalSyncScript(company) {
|
|
207
|
+
return `hot-signal-sync-${company}.py`;
|
|
208
|
+
}
|
|
209
|
+
export function companyOfHotSignalSyncJob(job) {
|
|
210
|
+
if (job.name !== FLEET_HOT_SIGNAL_SYNC_NAME || typeof job.script !== "string")
|
|
211
|
+
return null;
|
|
212
|
+
const match = /^hot-signal-sync-([a-z0-9][a-z0-9_-]*)\.py$/i.exec(path.basename(job.script));
|
|
213
|
+
return match ? match[1] : null;
|
|
214
|
+
}
|
|
215
|
+
export function renderFleetHotSignalSyncScript(input) {
|
|
216
|
+
const args = input.signalsEngine === false
|
|
217
|
+
? ["sources", "sync", "--company", input.company, "--hq-root", input.hqRoot]
|
|
218
|
+
: ["signals", "run", "--trigger", "job", "--company", input.company, "--hq-root", input.hqRoot, "--report-found"];
|
|
219
|
+
// The engine prints only when it finds new signals (--report-found), so its
|
|
220
|
+
// stdout goes to the owner's DM as is. The plain sync prints a report every
|
|
221
|
+
// run, so with the flag off its stdout goes to the log and the owner hears
|
|
222
|
+
// only about a run that failed (for example, nobody signed in).
|
|
223
|
+
const deliver = input.signalsEngine === false
|
|
224
|
+
? [
|
|
225
|
+
" with open(LOG, 'a', encoding='utf-8') as log:",
|
|
226
|
+
" log.write(result.stdout)",
|
|
227
|
+
" if result.returncode != 0:",
|
|
228
|
+
` sys.stdout.write(${JSON.stringify(`The 06:30 hot-channel sync for ${input.company} did not finish. Details are in `)} + LOG + '\\n')`,
|
|
229
|
+
]
|
|
230
|
+
: [" sys.stdout.write(result.stdout)"];
|
|
231
|
+
return [
|
|
232
|
+
"import subprocess, sys",
|
|
233
|
+
`NODE = ${JSON.stringify(input.nodeBinary)}`,
|
|
234
|
+
`HQ = ${JSON.stringify(input.hqBinary)}`,
|
|
235
|
+
`ARGS = ${JSON.stringify(args)}`,
|
|
236
|
+
`LOG = ${JSON.stringify(input.logFile)}`,
|
|
237
|
+
"try:",
|
|
238
|
+
" with open(LOG, 'a', encoding='utf-8') as log:",
|
|
239
|
+
" result = subprocess.run([NODE, HQ, *ARGS], stdout=subprocess.PIPE, stderr=log, text=True)",
|
|
240
|
+
...deliver,
|
|
241
|
+
"except OSError as exc:",
|
|
242
|
+
" with open(LOG, 'a', encoding='utf-8') as log:",
|
|
243
|
+
" log.write('hot-signal-sync could not run hq: ' + str(exc) + '\\n')",
|
|
244
|
+
"",
|
|
245
|
+
].join("\n");
|
|
246
|
+
}
|
|
247
|
+
export function fleetHotSignalSyncCompanies(config, activeCompany, ownerCompanies = []) {
|
|
248
|
+
const single = currentHotSignalSyncCompany(config, activeCompany);
|
|
249
|
+
if (config.companySlug || effectiveBotCompanies(config).length > 0 || effectiveBotKind(config) === "company") {
|
|
250
|
+
return single ? [single] : [];
|
|
251
|
+
}
|
|
252
|
+
const owned = [...new Set(ownerCompanies.map((slug) => slug.trim()).filter((slug) => slug && slug !== "personal"))].sort();
|
|
253
|
+
if (owned.length > 0)
|
|
254
|
+
return owned;
|
|
255
|
+
return single ? [single] : [];
|
|
256
|
+
}
|
|
257
|
+
export function ensureFleetHotSignalSync(input) {
|
|
258
|
+
const companies = fleetHotSignalSyncCompanies(input.config, input.activeCompany, input.ownerCompanies);
|
|
259
|
+
const wanted = new Set(companies);
|
|
260
|
+
const jobs = input.ops.list();
|
|
261
|
+
const removed = [];
|
|
262
|
+
for (const job of jobs) {
|
|
263
|
+
const jobCompany = companyOfHotSignalSyncJob(job);
|
|
264
|
+
if (jobCompany !== null && !wanted.has(jobCompany) && input.ops.remove(job.id))
|
|
265
|
+
removed.push(job.id);
|
|
266
|
+
}
|
|
267
|
+
forgetHotSignalSyncRegistrationsExcept(input.dir, companies);
|
|
268
|
+
const results = [];
|
|
269
|
+
let remaining = jobs.filter((job) => !removed.includes(job.id));
|
|
270
|
+
for (const company of companies) {
|
|
271
|
+
const result = ensureFleetHotSignalSyncFor(input, company, remaining);
|
|
272
|
+
if (result.job && !remaining.some((job) => job.id === result.job.id))
|
|
273
|
+
remaining = [...remaining, result.job];
|
|
274
|
+
results.push(result);
|
|
275
|
+
}
|
|
276
|
+
return { companies: results, removed };
|
|
277
|
+
}
|
|
278
|
+
function ensureFleetHotSignalSyncFor(input, company, jobs) {
|
|
279
|
+
const scriptName = fleetHotSignalSyncScript(company);
|
|
280
|
+
const scriptsDir = path.join(input.profileDir, "scripts");
|
|
281
|
+
fs.mkdirSync(scriptsDir, { recursive: true, mode: 0o700 });
|
|
282
|
+
const logFile = path.join(input.dir, "logs", "hot-signal-sync.log");
|
|
283
|
+
fs.mkdirSync(path.dirname(logFile), { recursive: true, mode: 0o700 });
|
|
284
|
+
const scriptFile = path.join(scriptsDir, scriptName);
|
|
285
|
+
const temporary = `${scriptFile}.${process.pid}.tmp`;
|
|
286
|
+
fs.writeFileSync(temporary, renderFleetHotSignalSyncScript({
|
|
287
|
+
nodeBinary: input.nodeBinary,
|
|
288
|
+
hqBinary: input.hqBinary,
|
|
289
|
+
company,
|
|
290
|
+
hqRoot: input.config.hqRoot,
|
|
291
|
+
logFile,
|
|
292
|
+
signalsEngine: input.signalsJobEnabled === true,
|
|
293
|
+
}), { mode: 0o600 });
|
|
294
|
+
fs.renameSync(temporary, scriptFile);
|
|
295
|
+
const current = jobs.find((job) => companyOfHotSignalSyncJob(job) === company) ?? null;
|
|
296
|
+
if (fleetHotSignalSyncRegistered(input.dir, company))
|
|
297
|
+
return { company, created: false, job: current };
|
|
298
|
+
if (current) {
|
|
299
|
+
markFleetHotSignalSyncRegistered(input.dir, company, input.now);
|
|
300
|
+
return { company, created: false, job: current };
|
|
301
|
+
}
|
|
302
|
+
const heldBy = otherBotWithHotSignalSync(input.dir, company, input.otherBotDirs);
|
|
303
|
+
if (heldBy)
|
|
304
|
+
return { company, created: false, job: null, heldBy };
|
|
305
|
+
const job = input.ops.create({
|
|
306
|
+
name: FLEET_HOT_SIGNAL_SYNC_NAME,
|
|
307
|
+
prompt: input.signalsJobEnabled === true
|
|
308
|
+
? `Run the signals engine for ${company} and post to the owner only when it finds new signals.`
|
|
309
|
+
: `Run the hot-channel sync for ${company}.`,
|
|
310
|
+
schedule: FLEET_HOT_SIGNAL_SYNC_SCHEDULE,
|
|
311
|
+
script: scriptName,
|
|
312
|
+
noAgent: true,
|
|
313
|
+
origin: fleetOwnerOrigin(input.config.ownerUid, [...jobs]),
|
|
314
|
+
workdir: input.config.hqRoot,
|
|
315
|
+
});
|
|
316
|
+
markFleetHotSignalSyncRegistered(input.dir, company, input.now);
|
|
317
|
+
return { company, created: true, job };
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=fleet-cron.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type BotEngineMetadata } from "./config.js";
|
|
2
2
|
import type { BotMachineCreds } from "./creds.js";
|
|
3
3
|
import { type FleetPython } from "./fleet-python.js";
|
|
4
|
+
import { vaultApiFetch } from "../../utils/vault-api.js";
|
|
4
5
|
import type { LocalBotPromotionRuntime } from "./promote.js";
|
|
5
6
|
export interface FleetLocalReleasePin {
|
|
6
7
|
repository: string;
|
|
@@ -41,6 +42,7 @@ export interface FleetLocalProfile {
|
|
|
41
42
|
transport?: string;
|
|
42
43
|
};
|
|
43
44
|
ownerCompanies?: string[];
|
|
45
|
+
autoApprove?: boolean;
|
|
44
46
|
hqRoot: string;
|
|
45
47
|
profileDir: string;
|
|
46
48
|
runtime: {
|
|
@@ -60,7 +62,7 @@ export interface FleetLocalInstallDeps {
|
|
|
60
62
|
hqReleaseLinks?: (release: FleetLocalReleasePin) => Promise<Map<string, string> | null>;
|
|
61
63
|
now?: () => Date;
|
|
62
64
|
release?: FleetLocalReleasePin;
|
|
63
|
-
publicKey?: string;
|
|
65
|
+
publicKey?: string | readonly string[];
|
|
64
66
|
}
|
|
65
67
|
export interface FleetLocalProfileInput {
|
|
66
68
|
agentUid: string;
|
|
@@ -79,6 +81,8 @@ export interface FleetLocalProfileInput {
|
|
|
79
81
|
};
|
|
80
82
|
/** Companies the owner's own turns may use; other senders get none of them. */
|
|
81
83
|
ownerCompanies?: string[];
|
|
84
|
+
/** True turns the runtime's command approval prompts off for every sender (`hq bot create --auto-approve`). */
|
|
85
|
+
autoApprove?: boolean;
|
|
82
86
|
}
|
|
83
87
|
/** The model the HQ Fleet Runtime asks for when a Claude bot names none. */
|
|
84
88
|
export declare const FLEET_CLAUDE_DEFAULT_MODEL = "claude-opus-5-5";
|
|
@@ -92,10 +96,19 @@ export declare function fleetProviderForRuntime(runtime: string, model?: string)
|
|
|
92
96
|
/** True when a bot with this provider still needs `hq bot auth` before it can answer. */
|
|
93
97
|
export declare function fleetProviderNeedsSignIn(provider: FleetLocalProfile["provider"]): boolean;
|
|
94
98
|
type FleetLocalExec = (executable: string, args: string[], options: Record<string, unknown>) => Buffer | string;
|
|
99
|
+
/** spawnSync-shaped runner for steps whose output is copied through after they finish. */
|
|
100
|
+
export type FleetLocalSpawn = (executable: string, args: string[], options: Record<string, unknown>) => {
|
|
101
|
+
status: number | null;
|
|
102
|
+
stdout?: Buffer | string | null;
|
|
103
|
+
stderr?: Buffer | string | null;
|
|
104
|
+
error?: Error;
|
|
105
|
+
};
|
|
95
106
|
export interface FleetLocalBootstrapDeps {
|
|
96
107
|
fleetHome?: string;
|
|
97
108
|
platform?: NodeJS.Platform;
|
|
98
109
|
run?: FleetLocalExec;
|
|
110
|
+
/** Runs the install steps whose output is copied through. Defaults to spawnSync, or to `run` when only `run` is given. */
|
|
111
|
+
spawn?: FleetLocalSpawn;
|
|
99
112
|
start?: boolean;
|
|
100
113
|
python?: FleetPython;
|
|
101
114
|
}
|
|
@@ -162,9 +175,27 @@ export interface FleetLocalRemovalResult {
|
|
|
162
175
|
credentialsRemoved: number;
|
|
163
176
|
}
|
|
164
177
|
export declare const HQ_FLEET_LOCAL_RELEASE: FleetLocalReleasePin;
|
|
178
|
+
/** hq-fleet-local trust/release-public.pem (rotated 2026-10-30; signed v0.4.17). */
|
|
165
179
|
export declare const HQ_FLEET_LOCAL_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEASJoapvo0WMTg+Wu3Jvt0nzlXLOBEr+G1aJRi0JkEb4A=\n-----END PUBLIC KEY-----\n";
|
|
180
|
+
/** hq-fleet-local trust/release-public-v2.pem (added 2026-11-01; signs v0.4.18). */
|
|
181
|
+
export declare const HQ_FLEET_LOCAL_PUBLIC_KEY_V2 = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmgUi7pKTJUmf3yzwcuH65wSvn1NyJrDfZHZUX08sGN8=\n-----END PUBLIC KEY-----\n";
|
|
182
|
+
/** hq-fleet-local trust/release-public-v3.pem (added 2026-11-02; signs v0.4.20 and later). */
|
|
183
|
+
export declare const HQ_FLEET_LOCAL_PUBLIC_KEY_V3 = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA2NUo6F38D4Kjxmy5qz5ytKRVRwocEvPk8lXqfwB2kS0=\n-----END PUBLIC KEY-----\n";
|
|
184
|
+
/** Every key a release manifest may be signed with. Any one must verify it. */
|
|
185
|
+
export declare const HQ_FLEET_LOCAL_PUBLIC_KEYS: readonly string[];
|
|
186
|
+
/** True when any trusted Ed25519 key verifies the manifest signature. */
|
|
187
|
+
export declare function fleetLocalManifestSignatureValid(manifest: Buffer, signature: Buffer, publicKey?: string | readonly string[]): boolean;
|
|
166
188
|
export declare function fleetHome(home?: string, env?: NodeJS.ProcessEnv): string;
|
|
167
|
-
export declare function verifyFleetLocalRelease(files: FleetLocalReleaseFiles, release?: FleetLocalReleasePin, publicKey?: string): void;
|
|
189
|
+
export declare function verifyFleetLocalRelease(files: FleetLocalReleaseFiles, release?: FleetLocalReleasePin, publicKey?: string | readonly string[]): void;
|
|
190
|
+
/**
|
|
191
|
+
* Check an extracted distribution against the signed manifest: every payload
|
|
192
|
+
* file present with its hash, and nothing else but the release metadata.
|
|
193
|
+
*/
|
|
194
|
+
export declare function verifyExtractedDistribution(dir: string, manifest: Buffer, version: string): void;
|
|
195
|
+
/** Write a ZIP archive's files under `target` with the same reader that verified it. */
|
|
196
|
+
export declare function extractZipEntries(archive: Buffer, target: string, version: string): void;
|
|
197
|
+
/** Every file in a ZIP archive by name (stored and deflated entries only; directories skipped). */
|
|
198
|
+
export declare function readZipEntries(archive: Buffer): Map<string, Buffer>;
|
|
168
199
|
/**
|
|
169
200
|
* Warning text when the signed manifest asks for a newer hq CLI than this
|
|
170
201
|
* one, or null. Advisory only: the pinned runtime is still installed, since
|
|
@@ -175,12 +206,60 @@ export declare function fleetLocalCliCompatibilityWarning(manifest: Buffer, rele
|
|
|
175
206
|
export declare const FLEET_RELEASE_TOKEN_TIMEOUT_MS = 15000;
|
|
176
207
|
export declare function resolveFleetReleaseToken(env?: NodeJS.ProcessEnv, run?: FleetLocalExec): string;
|
|
177
208
|
export declare function fetchHqFleetReleaseLinks(release: FleetLocalReleasePin): Promise<Map<string, string> | null>;
|
|
209
|
+
export declare const FLEET_LOCAL_LATEST_TIMEOUT_MS = 5000;
|
|
210
|
+
export declare const FLEET_LOCAL_LATEST_CACHE_MS: number;
|
|
211
|
+
export interface FleetLocalReleasePointer {
|
|
212
|
+
release: FleetLocalReleasePin;
|
|
213
|
+
minimumHqCli: string | null;
|
|
214
|
+
links: Map<string, string> | null;
|
|
215
|
+
linksExpireAt: number | null;
|
|
216
|
+
}
|
|
217
|
+
export interface FleetLocalTargetRelease {
|
|
218
|
+
release: FleetLocalReleasePin;
|
|
219
|
+
source: "pointer" | "compiled";
|
|
220
|
+
links: Map<string, string> | null;
|
|
221
|
+
linksExpireAt: number | null;
|
|
222
|
+
}
|
|
223
|
+
export declare function parseFleetLocalReleasePin(value: unknown): FleetLocalReleasePin | null;
|
|
224
|
+
export declare function parseFleetLocalReleasePointer(body: unknown, now?: number): FleetLocalReleasePointer | null;
|
|
225
|
+
export declare function chooseFleetLocalTargetRelease(pointer: FleetLocalReleasePointer | null, compiled?: FleetLocalReleasePin, cliVersion?: string): FleetLocalTargetRelease;
|
|
226
|
+
export declare function fetchFleetLocalReleasePointer(deps?: {
|
|
227
|
+
token?: () => Promise<string>;
|
|
228
|
+
fetchApi?: typeof vaultApiFetch;
|
|
229
|
+
now?: () => number;
|
|
230
|
+
}): Promise<FleetLocalReleasePointer | null>;
|
|
231
|
+
export declare function resetFleetLocalReleasePointerCache(): void;
|
|
232
|
+
interface FleetLocalPointerDeps {
|
|
233
|
+
fleetHome?: string;
|
|
234
|
+
now?: () => number;
|
|
235
|
+
fetchPointer?: () => Promise<FleetLocalReleasePointer | null>;
|
|
236
|
+
}
|
|
237
|
+
export declare function resolveFleetLocalTargetRelease(deps?: FleetLocalPointerDeps & {
|
|
238
|
+
compiled?: FleetLocalReleasePin;
|
|
239
|
+
cliVersion?: string;
|
|
240
|
+
}): Promise<FleetLocalTargetRelease>;
|
|
241
|
+
export declare function resolveFleetLocalPointerTarget(deps?: FleetLocalPointerDeps & {
|
|
242
|
+
cliVersion?: string;
|
|
243
|
+
}): Promise<FleetLocalTargetRelease | null>;
|
|
244
|
+
export declare function installTargetFleetLocalDistribution(deps?: Omit<FleetLocalInstallDeps, "release"> & {
|
|
245
|
+
target?: FleetLocalTargetRelease;
|
|
246
|
+
now?: () => number;
|
|
247
|
+
}): Promise<FleetLocalInstallation>;
|
|
178
248
|
export declare const FLEET_LOCAL_METADATA_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
179
249
|
export declare const FLEET_LOCAL_ARCHIVE_DOWNLOAD_TIMEOUT_MS: number;
|
|
180
250
|
export declare const FLEET_LOCAL_RUNTIME_DOWNLOAD_TIMEOUT_MS: number;
|
|
181
251
|
export declare function installPinnedFleetLocalDistribution(deps?: FleetLocalInstallDeps): Promise<FleetLocalInstallation>;
|
|
182
252
|
/** The process id the bot's gateway recorded, when its file reads; the caller checks whether it is alive. */
|
|
183
253
|
export declare function fleetLocalGatewayPid(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome">): number | null;
|
|
254
|
+
/**
|
|
255
|
+
* Whether the bot's HQ Fleet gateway is installed as a login service. The
|
|
256
|
+
* runtime registers it with launchd as `ai.hq-fleet.gateway-<profile>`; null
|
|
257
|
+
* on platforms where hq-cli does not know the service layout.
|
|
258
|
+
*/
|
|
259
|
+
export declare function fleetLocalServiceInstalled(agentUid: string, deps?: {
|
|
260
|
+
platform?: NodeJS.Platform;
|
|
261
|
+
home?: string;
|
|
262
|
+
}): boolean | null;
|
|
184
263
|
export declare function fleetLocalProfileNeedsAdoption(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome" | "platform"> & {
|
|
185
264
|
release?: FleetLocalReleasePin;
|
|
186
265
|
}): boolean;
|
|
@@ -202,10 +281,42 @@ export declare function writeFleetLocalSoul(agentUid: string, systemPrompt: stri
|
|
|
202
281
|
* the bot's own interpreter, says beforehand what it would refuse.
|
|
203
282
|
*/
|
|
204
283
|
export declare function scanFleetLocalInstructions(agentUid: string, text: string, deps?: FleetLocalControlDeps): string[];
|
|
284
|
+
export declare function fleetLocalRuntimePython(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome" | "platform">): {
|
|
285
|
+
python: string;
|
|
286
|
+
source: string;
|
|
287
|
+
profileDir: string;
|
|
288
|
+
};
|
|
289
|
+
export declare function fleetProfileOwnerCompanies(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome">): string[];
|
|
290
|
+
export declare function fleetLocalProfileDir(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome">): string;
|
|
291
|
+
export interface FleetLocalGatewayState {
|
|
292
|
+
pid: number | null;
|
|
293
|
+
gatewayState: string | null;
|
|
294
|
+
activeAgents: number;
|
|
295
|
+
platforms: Record<string, string>;
|
|
296
|
+
}
|
|
297
|
+
export declare function readFleetLocalGatewayState(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome">): FleetLocalGatewayState | null;
|
|
298
|
+
export declare function fleetLocalChannels(state: FleetLocalGatewayState | null, gatewayAlive: boolean): {
|
|
299
|
+
slack: string;
|
|
300
|
+
telegram: string;
|
|
301
|
+
};
|
|
302
|
+
export declare function fleetLocalBusyReason(agentUid: string, deps?: Pick<FleetLocalControlDeps, "fleetHome"> & {
|
|
303
|
+
isAlive?: (pid: number) => boolean;
|
|
304
|
+
}): string | null;
|
|
205
305
|
/** Checks the instructions with the runtime's scanner, then makes them the bot's persona. */
|
|
206
306
|
export declare function refreshFleetLocalInstructions(agentUid: string, systemPrompt: string, deps?: FleetLocalControlDeps): string;
|
|
207
307
|
/** Last few non-empty stderr lines of a failed child process, trimmed for an error message. */
|
|
208
308
|
export declare function stderrTail(error: unknown): string;
|
|
309
|
+
/** A FleetLocalSpawn backed by an execFileSync-shaped runner (stderr is only known on failure). */
|
|
310
|
+
export declare function spawnFromRun(run: FleetLocalExec): FleetLocalSpawn;
|
|
311
|
+
/**
|
|
312
|
+
* Replaces inherited stdio slots (an fd number or "inherit") with "pipe".
|
|
313
|
+
* `forward` is true when any slot was replaced, so the caller copies the
|
|
314
|
+
* captured output to this process's stderr.
|
|
315
|
+
*/
|
|
316
|
+
export declare function pipeInheritedStdio(stdio: unknown): {
|
|
317
|
+
stdio: unknown;
|
|
318
|
+
forward: boolean;
|
|
319
|
+
};
|
|
209
320
|
/**
|
|
210
321
|
* Message for a Windows extraction that cannot fit under MAX_PATH, or null
|
|
211
322
|
* when it fits or long paths are on. `longest` is the longest member name in
|