@indigoai-us/hq-cli 5.345.191 → 5.345.194
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 +431 -0
- package/assets/bot-workers/setup/worker.yaml +91 -34
- package/dist/command-catalog.generated.d.ts +145 -19
- package/dist/command-catalog.generated.js +184 -21
- package/dist/commands/bot-jobs.d.ts +21 -18
- package/dist/commands/bot-jobs.js +127 -39
- package/dist/commands/bot.d.ts +4 -3
- package/dist/commands/bot.js +265 -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 +46 -0
- package/dist/commands/signals-run.js +180 -0
- package/dist/commands/signals.d.ts +1 -0
- package/dist/commands/signals.js +3 -0
- package/dist/commands/sources.d.ts +58 -0
- package/dist/commands/sources.js +294 -26
- package/dist/commands/staff/reset-test-account.d.ts +10 -0
- package/dist/commands/staff/reset-test-account.js +18 -2
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.js +35 -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 +93 -1
- package/dist/lib/bot/fleet-local.js +546 -34
- 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.d.ts +6 -0
- package/dist/lib/hot-channels/loop.js +19 -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 +34 -2
- package/dist/lib/hot-channels/signals-pass.js +149 -38
- package/dist/lib/hot-channels/signals-redo.d.ts +60 -0
- package/dist/lib/hot-channels/signals-redo.js +207 -0
- 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 +202 -0
- package/dist/lib/signals/engine.js +504 -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 +118 -0
- package/dist/lib/signals/steps/extract.js +793 -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 +117 -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/dist/utils/vault-api.d.ts +1 -0
- package/dist/utils/vault-api.js +1 -1
- 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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapters step: one hot-channel sync per company through
|
|
3
|
+
* runCompanyHotChannelSync (src/commands/sources.ts), which wires
|
|
4
|
+
* runOnDemandSync from src/lib/hot-channels/run.ts with the gateway deps,
|
|
5
|
+
* sign-in check and sync lock. The adapters write under
|
|
6
|
+
* companies/{co}/sources/ and companies/{co}/signals/ themselves.
|
|
7
|
+
*
|
|
8
|
+
* US-008: core/settings/signals-adapters.yaml gates adapters locally (an
|
|
9
|
+
* adapter off there is skipped with reason flag-off and the rest run in one
|
|
10
|
+
* sync), and after the sync the signed-in person's vault cursors are mirrored
|
|
11
|
+
* to workspace/signals/watermarks/{co}/{cursorKey}.json through ctx.write.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from "node:fs";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { FLAG_OFF_REASON, gateAdapters, readSignalsAdaptersCatalog } from "../adapters-catalog.js";
|
|
16
|
+
import { assertNoEscapingLinks } from "../write-guard.js";
|
|
17
|
+
export const defaultHotChannelSync = async (input) => {
|
|
18
|
+
const { runCompanyHotChannelSync } = await import("../../../commands/sources.js");
|
|
19
|
+
return runCompanyHotChannelSync(input);
|
|
20
|
+
};
|
|
21
|
+
/** Adapters whose run record carries the token level (US-010). */
|
|
22
|
+
const TOKEN_LEVEL_ADAPTERS = new Set(["attio", "gmail"]);
|
|
23
|
+
export function mapSyncReport(report) {
|
|
24
|
+
if (report.signInRequired) {
|
|
25
|
+
return { status: "skipped", itemsIn: 0, itemsOut: 0, skippedReason: "no-login", byAdapter: {}, errorKind: "signed-out" };
|
|
26
|
+
}
|
|
27
|
+
if (report.skipped) {
|
|
28
|
+
return { status: "skipped", itemsIn: 0, itemsOut: 0, skippedReason: "sync-busy", byAdapter: {} };
|
|
29
|
+
}
|
|
30
|
+
const byAdapter = {};
|
|
31
|
+
const itemsInByAdapter = {};
|
|
32
|
+
const tokenLevels = {};
|
|
33
|
+
let itemsIn = 0;
|
|
34
|
+
let itemsOut = 0;
|
|
35
|
+
let ok = 0;
|
|
36
|
+
let failed = 0;
|
|
37
|
+
let reconnect = false;
|
|
38
|
+
for (const o of report.outcomes) {
|
|
39
|
+
byAdapter[o.adapter] = (byAdapter[o.adapter] ?? 0) + o.landed;
|
|
40
|
+
if (o.status !== "gated")
|
|
41
|
+
itemsInByAdapter[o.adapter] = (itemsInByAdapter[o.adapter] ?? 0) + o.landed + o.duplicates;
|
|
42
|
+
// A shared workspace token wins over a personal one when both ran.
|
|
43
|
+
if (o.tokenLevel && TOKEN_LEVEL_ADAPTERS.has(o.adapter) && tokenLevels[o.adapter] !== "workspace") {
|
|
44
|
+
tokenLevels[o.adapter] = o.tokenLevel;
|
|
45
|
+
}
|
|
46
|
+
itemsIn += o.landed + o.duplicates;
|
|
47
|
+
itemsOut += o.landed;
|
|
48
|
+
if (o.status === "ok")
|
|
49
|
+
ok += 1;
|
|
50
|
+
if (o.status === "failed")
|
|
51
|
+
failed += 1;
|
|
52
|
+
if (o.reconnect)
|
|
53
|
+
reconnect = true;
|
|
54
|
+
}
|
|
55
|
+
const result = { status: "ok", itemsIn, itemsOut, byAdapter };
|
|
56
|
+
if (Object.keys(itemsInByAdapter).length > 0)
|
|
57
|
+
result.itemsInByAdapter = itemsInByAdapter;
|
|
58
|
+
if (Object.keys(tokenLevels).length > 0)
|
|
59
|
+
result.tokenLevels = tokenLevels;
|
|
60
|
+
if (report.outcomes.length === 0) {
|
|
61
|
+
result.status = "skipped";
|
|
62
|
+
result.skippedReason = "no-channels";
|
|
63
|
+
}
|
|
64
|
+
else if (report.outcomes.every((o) => o.status === "gated")) {
|
|
65
|
+
result.status = "skipped";
|
|
66
|
+
result.skippedReason = FLAG_OFF_REASON;
|
|
67
|
+
}
|
|
68
|
+
else if (failed > 0) {
|
|
69
|
+
result.status = ok > 0 ? "partial" : "failed";
|
|
70
|
+
const first = report.outcomes.find((o) => o.status === "failed");
|
|
71
|
+
result.error = first?.message ?? "adapter failed";
|
|
72
|
+
result.errorKind = reconnect ? "reconnect" : "other";
|
|
73
|
+
}
|
|
74
|
+
else if (reconnect) {
|
|
75
|
+
result.errorKind = "reconnect";
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
async function builtinAdapterIds(hqRoot, company) {
|
|
80
|
+
const { createBuiltinHotChannelRegistry } = await import("../../hot-channels/adapters/index.js");
|
|
81
|
+
return createBuiltinHotChannelRegistry({ vaultRoot: path.join(hqRoot, "companies", company) })
|
|
82
|
+
.list()
|
|
83
|
+
.map((a) => a.id);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Mirror the signed-in person's vault cursors
|
|
87
|
+
* (`companies/{co}/sources/_cursors/@{personKey}/{key}.json`, written by the
|
|
88
|
+
* loop only after a page's sources land) to the local watermark
|
|
89
|
+
* `workspace/signals/watermarks/{co}/{key}.json`. Teammates' cursor
|
|
90
|
+
* directories are never read: their watermarks are not this machine's.
|
|
91
|
+
*/
|
|
92
|
+
export function mirrorWatermarks(ctx, personKey) {
|
|
93
|
+
const personDir = path.join(ctx.hqRoot, "companies", ctx.company, "sources", "_cursors", `@${personKey}`);
|
|
94
|
+
let files;
|
|
95
|
+
try {
|
|
96
|
+
files = fs.readdirSync(personDir).filter((f) => f.endsWith(".json")).sort();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const written = [];
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
const text = fs.readFileSync(path.join(personDir, file), "utf8");
|
|
104
|
+
try {
|
|
105
|
+
JSON.parse(text);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const rel = `workspace/signals/watermarks/${ctx.company}/${file}`;
|
|
111
|
+
ctx.write(rel, text.endsWith("\n") ? text : `${text}\n`);
|
|
112
|
+
written.push(rel);
|
|
113
|
+
}
|
|
114
|
+
return written;
|
|
115
|
+
}
|
|
116
|
+
export const adaptersStep = {
|
|
117
|
+
name: "adapters",
|
|
118
|
+
async run(ctx) {
|
|
119
|
+
// The hot-channel loop writes cursors, ledgers, locks, raw payloads and
|
|
120
|
+
// landed sources under companies/{co}/sources/, and the signals pass writes
|
|
121
|
+
// under companies/{co}/signals/, with plain fs. Fail closed before it runs
|
|
122
|
+
// if any link in either tree leaves this company's folder for that root.
|
|
123
|
+
for (const store of ["sources", "signals"]) {
|
|
124
|
+
assertNoEscapingLinks(ctx.hqRoot, `companies/${ctx.company}/${store}`, { company: ctx.company });
|
|
125
|
+
}
|
|
126
|
+
const sync = ctx.hotChannelSync ?? defaultHotChannelSync;
|
|
127
|
+
const ids = ctx.registeredAdapterIds ?? (await builtinAdapterIds(ctx.hqRoot, ctx.company));
|
|
128
|
+
const gating = await gateAdapters(ids, readSignalsAdaptersCatalog(ctx.hqRoot), ctx.isFlagOn);
|
|
129
|
+
const skipped = Object.keys(gating.skips).length > 0;
|
|
130
|
+
if (skipped && gating.enabled.length === 0) {
|
|
131
|
+
return { status: "skipped", itemsIn: 0, itemsOut: 0, skippedReason: FLAG_OFF_REASON, byAdapter: {}, adapterSkips: gating.skips };
|
|
132
|
+
}
|
|
133
|
+
const base = {
|
|
134
|
+
hqRoot: ctx.hqRoot,
|
|
135
|
+
company: ctx.company,
|
|
136
|
+
now: ctx.now,
|
|
137
|
+
trigger: ctx.trigger === "job" ? "scheduled" : "on-demand",
|
|
138
|
+
catchUp: ctx.catchUp,
|
|
139
|
+
...(ctx.isFlagOn ? { isFlagOn: ctx.isFlagOn } : {}),
|
|
140
|
+
};
|
|
141
|
+
// One sync for the enabled list: an enabled adapter the hq-pro catalog
|
|
142
|
+
// does not list just has nothing to run, instead of failing the step.
|
|
143
|
+
const report = await sync(skipped ? { ...base, onlyAdapters: gating.enabled } : base);
|
|
144
|
+
const result = mapSyncReport(report);
|
|
145
|
+
const adapterSkips = { ...gating.skips };
|
|
146
|
+
for (const o of report.outcomes)
|
|
147
|
+
if (o.status === "gated")
|
|
148
|
+
adapterSkips[o.adapter] = FLAG_OFF_REASON;
|
|
149
|
+
if (Object.keys(adapterSkips).length > 0)
|
|
150
|
+
result.adapterSkips = adapterSkips;
|
|
151
|
+
if (!report.signInRequired && !report.skipped && report.personKey)
|
|
152
|
+
mirrorWatermarks(ctx, report.personKey);
|
|
153
|
+
return result;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Name similarity for the garden step's merge-review queue. */
|
|
2
|
+
/** Lowercase, strip accents and punctuation, collapse whitespace. */
|
|
3
|
+
export declare function canonicalName(s: string): string;
|
|
4
|
+
/** Normalized Levenshtein similarity on canonical names, 0..1. */
|
|
5
|
+
export declare function nameSimilarity(a: string, b: string): number;
|
|
6
|
+
export declare const REVIEW_LOW = 0.8;
|
|
7
|
+
export declare const SAME_ENTITY = 0.95;
|
|
8
|
+
export type SimilarityBand = "distinct" | "uncertain" | "same";
|
|
9
|
+
export declare function similarityBand(sim: number): SimilarityBand;
|
|
10
|
+
//# sourceMappingURL=entity-similarity.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Name similarity for the garden step's merge-review queue. */
|
|
2
|
+
/** Lowercase, strip accents and punctuation, collapse whitespace. */
|
|
3
|
+
export function canonicalName(s) {
|
|
4
|
+
return s
|
|
5
|
+
.normalize("NFKD")
|
|
6
|
+
.replace(/[̀-ͯ]/g, "")
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^\p{L}\p{N}]+/gu, " ")
|
|
9
|
+
.trim();
|
|
10
|
+
}
|
|
11
|
+
function levenshtein(a, b) {
|
|
12
|
+
if (a === b)
|
|
13
|
+
return 0;
|
|
14
|
+
if (!a.length)
|
|
15
|
+
return b.length;
|
|
16
|
+
if (!b.length)
|
|
17
|
+
return a.length;
|
|
18
|
+
let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
19
|
+
for (let i = 1; i <= a.length; i++) {
|
|
20
|
+
const cur = [i];
|
|
21
|
+
for (let j = 1; j <= b.length; j++) {
|
|
22
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
23
|
+
cur.push(Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost));
|
|
24
|
+
}
|
|
25
|
+
prev = cur;
|
|
26
|
+
}
|
|
27
|
+
return prev[b.length];
|
|
28
|
+
}
|
|
29
|
+
/** Normalized Levenshtein similarity on canonical names, 0..1. */
|
|
30
|
+
export function nameSimilarity(a, b) {
|
|
31
|
+
const x = canonicalName(a);
|
|
32
|
+
const y = canonicalName(b);
|
|
33
|
+
if (!x && !y)
|
|
34
|
+
return 1;
|
|
35
|
+
const max = Math.max(x.length, y.length);
|
|
36
|
+
return 1 - levenshtein(x, y) / max;
|
|
37
|
+
}
|
|
38
|
+
export const REVIEW_LOW = 0.8;
|
|
39
|
+
export const SAME_ENTITY = 0.95;
|
|
40
|
+
export function similarityBand(sim) {
|
|
41
|
+
if (sim >= SAME_ENTITY)
|
|
42
|
+
return "same";
|
|
43
|
+
if (sim >= REVIEW_LOW)
|
|
44
|
+
return "uncertain";
|
|
45
|
+
return "distinct";
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=entity-similarity.js.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type BotRuntimeId } from "../../bot/config.js";
|
|
2
|
+
import type { SignalsStep } from "./types.js";
|
|
3
|
+
export declare const EXTRACT_SIGNAL_TYPES: readonly ["action_item", "commitment", "decision", "risk", "question", "key_point", "participant_contribution", "summary"];
|
|
4
|
+
export declare const DEFAULT_WORKLIST_LIMIT = 20;
|
|
5
|
+
export declare const DEFAULT_TURN_TIMEOUT_MS: number;
|
|
6
|
+
export declare const CODEX_PERMISSION_PROFILE = "hq_signals_extract";
|
|
7
|
+
export declare const CANDIDATE_WRAPPER_NAME = "write-candidate.sh";
|
|
8
|
+
/** The only tools a claude turn may use: Read inside the channel folder and the pinned wrapper. */
|
|
9
|
+
export declare function claudeAllowedTools(channelDir: string, wrapperPath: string): string[];
|
|
10
|
+
export interface ExtractStepOptions {
|
|
11
|
+
/** Runtime when no main local bot config is found. Default claude. */
|
|
12
|
+
runtime?: BotRuntimeId;
|
|
13
|
+
/** Returns the main local bot's runtime, or null. Default reads ~/.hq/bots. */
|
|
14
|
+
resolveBotRuntime?: () => BotRuntimeId | null;
|
|
15
|
+
claudeBin?: string;
|
|
16
|
+
codexBin?: string;
|
|
17
|
+
worklistLimit?: number;
|
|
18
|
+
turnTimeoutMs?: number;
|
|
19
|
+
/** Run channels whose source.yaml says run: cloud too (passes --force). */
|
|
20
|
+
force?: boolean;
|
|
21
|
+
}
|
|
22
|
+
interface SourceChannel {
|
|
23
|
+
channel: string;
|
|
24
|
+
force: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface WorkItem {
|
|
27
|
+
file: string;
|
|
28
|
+
audience_key?: string;
|
|
29
|
+
audience?: string[];
|
|
30
|
+
skip?: string;
|
|
31
|
+
}
|
|
32
|
+
/** First personal bot under ~/.hq/bots (by name) with a readable config. */
|
|
33
|
+
export declare function defaultResolveBotRuntime(root?: string): BotRuntimeId | null;
|
|
34
|
+
/**
|
|
35
|
+
* The channel of a `--redo` item, which must be written `sources/<channel>/<file>.md`,
|
|
36
|
+
* or null when it is not in that form.
|
|
37
|
+
*/
|
|
38
|
+
export declare function redoItemChannel(item: string): string | null;
|
|
39
|
+
/** Declared source channels with run: local (or any run: when forced). */
|
|
40
|
+
export declare function listSourceChannels(hqRoot: string, company: string, force?: boolean): SourceChannel[];
|
|
41
|
+
/** Shell single-quote a value so a generated script carries it as data. */
|
|
42
|
+
export declare function shellQuote(value: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Refuse a worklist item whose path or audience could break out of the prompt
|
|
45
|
+
* or the channel folder. Returns the reason, or null when the item is safe.
|
|
46
|
+
*/
|
|
47
|
+
export declare function unsafeItemReason(item: WorkItem, channel: string): string | null;
|
|
48
|
+
export declare function buildExtractPrompt(input: {
|
|
49
|
+
skillText: string;
|
|
50
|
+
company: string;
|
|
51
|
+
channel: string;
|
|
52
|
+
item: WorkItem;
|
|
53
|
+
itemPath: string;
|
|
54
|
+
wrapperPath: string;
|
|
55
|
+
/** codex has no Read tool; it reads with shell commands inside its sandbox. */
|
|
56
|
+
runtime?: "claude" | "codex";
|
|
57
|
+
}): string;
|
|
58
|
+
/**
|
|
59
|
+
* The per-item candidate command. It pins --company, --audience and
|
|
60
|
+
* --source-ref (a repeated flag must match the pinned value), refuses
|
|
61
|
+
* --body-file and any other flag, and calls ontology-candidate.sh write.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildCandidateWrapper(input: {
|
|
64
|
+
hqRoot: string;
|
|
65
|
+
company: string;
|
|
66
|
+
audience: string;
|
|
67
|
+
sourceRef: string;
|
|
68
|
+
}): string;
|
|
69
|
+
/** Parse a stream-json transcript (or a codex --json event stream). */
|
|
70
|
+
export declare function parseTurnOutput(stdout: string): {
|
|
71
|
+
result: Record<string, unknown> | null;
|
|
72
|
+
turns: number;
|
|
73
|
+
costUsd: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Clean up the new candidate files a turn produced.
|
|
77
|
+
*
|
|
78
|
+
* With `scope`, only this item's files are touched: a file is this item's when
|
|
79
|
+
* its source_ref is the wrapper-pinned `scope.sourceRef`. Every other new file
|
|
80
|
+
* (another company's garden or extract, a /meeting-notes session, another
|
|
81
|
+
* source, garden moving a candidate into _done/) is left as it is and not
|
|
82
|
+
* counted.
|
|
83
|
+
* - In companies/<company>/: this item's file is kept when it conforms and
|
|
84
|
+
* deleted when it does not.
|
|
85
|
+
* - In another company: this item's file is deleted and listed under `foreign`,
|
|
86
|
+
* unless that company has its own source item with the same channel and file
|
|
87
|
+
* name (then the file is that company's candidate, not a leak).
|
|
88
|
+
* Every delete goes through the company-scoped write guard.
|
|
89
|
+
*/
|
|
90
|
+
export declare function validateNewCandidates(files: string[], expectedAudienceKey: string | undefined, scope: {
|
|
91
|
+
hqRoot: string;
|
|
92
|
+
company: string;
|
|
93
|
+
sourceRef: string;
|
|
94
|
+
}): {
|
|
95
|
+
kept: number;
|
|
96
|
+
rejected: number;
|
|
97
|
+
foreign: string[];
|
|
98
|
+
};
|
|
99
|
+
/** Paths a turn may touch, all resolved through symlinks. */
|
|
100
|
+
export interface TurnScope {
|
|
101
|
+
hqRoot: string;
|
|
102
|
+
company: string;
|
|
103
|
+
/** companies/{co}/sources/{channel}, realpath. */
|
|
104
|
+
channelDir: string;
|
|
105
|
+
/** The turn's temp cwd holding the wrapper, realpath. */
|
|
106
|
+
turnDir: string;
|
|
107
|
+
wrapperPath: string;
|
|
108
|
+
/** companies/{co}/{signals,ontology}/_candidates, realpath. */
|
|
109
|
+
candidateDirs: string[];
|
|
110
|
+
}
|
|
111
|
+
/** TOML inline table for the codex permission profile's filesystem entries. */
|
|
112
|
+
export declare function codexFilesystemProfile(scope: TurnScope, codexBin: string, envPath: string | undefined): string;
|
|
113
|
+
export declare function claudeTurnArgs(prompt: string, scope: TurnScope, maxTurns: number, budgetUsd: number): string[];
|
|
114
|
+
export declare function codexTurnArgs(prompt: string, scope: TurnScope, codexBin: string, envPath: string | undefined): string[];
|
|
115
|
+
export declare function createExtractStep(options?: ExtractStepOptions): SignalsStep;
|
|
116
|
+
export declare const extractStep: SignalsStep;
|
|
117
|
+
export {};
|
|
118
|
+
//# sourceMappingURL=extract.d.ts.map
|