@forwardimpact/outpost 3.1.4 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/fit-outpost.js +6 -15
- package/package.json +7 -2
- package/src/agent-runner.js +10 -3
- package/src/kb-manager.js +12 -10
- package/src/outpost.js +2 -3
- package/src/scheduler.js +1 -1
- package/src/socket-server.js +1 -2
package/bin/fit-outpost.js
CHANGED
|
@@ -3,24 +3,15 @@
|
|
|
3
3
|
// bag, threaded into src/outpost.js's dispatch via run(runtime, version).
|
|
4
4
|
import "@forwardimpact/libpreflight/node22";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { dirname, join } from "node:path";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
|
|
6
|
+
import { resolveVersion } from "@forwardimpact/libcli";
|
|
10
7
|
import { createDefaultRuntime } from "@forwardimpact/libutil/runtime";
|
|
11
8
|
|
|
12
9
|
import { run } from "../src/outpost.js";
|
|
13
10
|
|
|
14
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
|
|
16
|
-
// In compiled binaries (bun build --compile), `bun build --define` injects the
|
|
17
|
-
// version string here so the readFileSync branch is eliminated as dead code.
|
|
18
|
-
// Source execution falls through to package.json.
|
|
19
|
-
const VERSION =
|
|
20
|
-
process.env.OUTPOST_VERSION ||
|
|
21
|
-
JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"))
|
|
22
|
-
.version;
|
|
23
|
-
|
|
24
11
|
const runtime = createDefaultRuntime();
|
|
25
|
-
const
|
|
12
|
+
const version = resolveVersion({
|
|
13
|
+
packageJsonUrl: new URL("../package.json", import.meta.url),
|
|
14
|
+
runtime,
|
|
15
|
+
});
|
|
16
|
+
const code = await run(runtime, version);
|
|
26
17
|
if (code) runtime.proc.exit(code);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/outpost",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Personal operations center — context from email, calendar, and knowledge assembled so preparation is continuous, not a morning scramble.",
|
|
5
5
|
"homepage": "https://www.forwardimpact.team",
|
|
6
6
|
"repository": {
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@forwardimpact/libcli": "^0.1.0",
|
|
53
|
-
"@forwardimpact/libmacos": "^0.1.0",
|
|
54
53
|
"@forwardimpact/libpreflight": "^0.1.0",
|
|
55
54
|
"@forwardimpact/libtelemetry": "^0.1.33",
|
|
56
55
|
"@forwardimpact/libutil": "^0.1.0"
|
|
@@ -58,10 +57,16 @@
|
|
|
58
57
|
"devDependencies": {
|
|
59
58
|
"@forwardimpact/libmock": "^0.1.0"
|
|
60
59
|
},
|
|
60
|
+
"optionalDependencies": {
|
|
61
|
+
"@forwardimpact/libmacos": "^0.1.0"
|
|
62
|
+
},
|
|
61
63
|
"engines": {
|
|
62
64
|
"bun": ">=1.2.0",
|
|
63
65
|
"node": ">=22.0.0"
|
|
64
66
|
},
|
|
67
|
+
"os": [
|
|
68
|
+
"darwin"
|
|
69
|
+
],
|
|
65
70
|
"publishConfig": {
|
|
66
71
|
"access": "public"
|
|
67
72
|
}
|
package/src/agent-runner.js
CHANGED
|
@@ -16,6 +16,7 @@ export class AgentRunner {
|
|
|
16
16
|
#fs;
|
|
17
17
|
#proc;
|
|
18
18
|
#clock;
|
|
19
|
+
#runtime;
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* @param {Object | (() => Object | Promise<{default?: Object}>)} spawn -
|
|
@@ -43,6 +44,7 @@ export class AgentRunner {
|
|
|
43
44
|
this.#fs = runtime.fs;
|
|
44
45
|
this.#proc = runtime.proc;
|
|
45
46
|
this.#clock = runtime.clock;
|
|
47
|
+
this.#runtime = runtime;
|
|
46
48
|
this.#activeChildren = new Set();
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -181,14 +183,19 @@ export class AgentRunner {
|
|
|
181
183
|
spawnArgs,
|
|
182
184
|
env,
|
|
183
185
|
kbPath,
|
|
186
|
+
this.#runtime,
|
|
184
187
|
);
|
|
185
188
|
this.#activeChildren.add(pid);
|
|
186
189
|
|
|
187
|
-
const exitCode = await spawnMod.waitForExit(
|
|
190
|
+
const exitCode = await spawnMod.waitForExit(
|
|
191
|
+
pid,
|
|
192
|
+
undefined,
|
|
193
|
+
this.#runtime,
|
|
194
|
+
);
|
|
188
195
|
this.#activeChildren.delete(pid);
|
|
189
196
|
|
|
190
|
-
const stdout = spawnMod.readOutput(stdoutFile);
|
|
191
|
-
const stderr = spawnMod.readOutput(stderrFile);
|
|
197
|
+
const stdout = spawnMod.readOutput(stdoutFile, this.#runtime);
|
|
198
|
+
const stderr = spawnMod.readOutput(stderrFile, this.#runtime);
|
|
192
199
|
|
|
193
200
|
if (exitCode === 0) {
|
|
194
201
|
this.#log(
|
package/src/kb-manager.js
CHANGED
|
@@ -6,11 +6,10 @@ import { join, dirname, resolve } from "node:path";
|
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { createLogger } from "@forwardimpact/libtelemetry";
|
|
8
8
|
|
|
9
|
-
const logger = createLogger("outpost");
|
|
10
|
-
|
|
11
9
|
/** Manage knowledge base lifecycle including initialization, updates, and settings merging. */
|
|
12
10
|
export class KBManager {
|
|
13
11
|
#fs;
|
|
12
|
+
#logger;
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* @param {import("@forwardimpact/libutil/runtime").Runtime} runtime
|
|
@@ -21,6 +20,7 @@ export class KBManager {
|
|
|
21
20
|
if (!runtime?.fs) throw new Error("runtime.fs is required");
|
|
22
21
|
if (!logFn) throw new Error("logFn is required");
|
|
23
22
|
this.#fs = runtime.fs;
|
|
23
|
+
this.#logger = createLogger("outpost", runtime);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -74,12 +74,12 @@ export class KBManager {
|
|
|
74
74
|
*/
|
|
75
75
|
async copyBundledFiles(tpl, dest) {
|
|
76
76
|
await this.#fs.copyFile(join(tpl, "CLAUDE.md"), join(dest, "CLAUDE.md"));
|
|
77
|
-
logger.info(` Updated CLAUDE.md`);
|
|
77
|
+
this.#logger.info(` Updated CLAUDE.md`);
|
|
78
78
|
|
|
79
79
|
const apmSrc = join(tpl, "apm.yml");
|
|
80
80
|
if (await this.#exists(apmSrc)) {
|
|
81
81
|
await this.#fs.copyFile(apmSrc, join(dest, "apm.yml"));
|
|
82
|
-
logger.info(` Updated apm.yml`);
|
|
82
|
+
this.#logger.info(` Updated apm.yml`);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
await this.mergeSettings(tpl, dest);
|
|
@@ -96,7 +96,9 @@ export class KBManager {
|
|
|
96
96
|
const names = entries.map((d) =>
|
|
97
97
|
sub === "agents" ? d.name.replace(".md", "") : d.name,
|
|
98
98
|
);
|
|
99
|
-
logger.info(
|
|
99
|
+
this.#logger.info(
|
|
100
|
+
` Updated ${names.length} ${sub}: ${names.join(", ")}`,
|
|
101
|
+
);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
|
|
@@ -141,7 +143,7 @@ export class KBManager {
|
|
|
141
143
|
if (!(await this.#exists(destPath))) {
|
|
142
144
|
await this.#ensureDir(join(dest, ".claude"));
|
|
143
145
|
await this.#fs.copyFile(src, destPath);
|
|
144
|
-
logger.info(` Created settings.json`);
|
|
146
|
+
this.#logger.info(` Created settings.json`);
|
|
145
147
|
return;
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -154,9 +156,9 @@ export class KBManager {
|
|
|
154
156
|
|
|
155
157
|
if (added > 0) {
|
|
156
158
|
await this.#writeJSON(destPath, existing);
|
|
157
|
-
logger.info(` Updated settings.json (${added} new entries)`);
|
|
159
|
+
this.#logger.info(` Updated settings.json (${added} new entries)`);
|
|
158
160
|
} else {
|
|
159
|
-
logger.info(` Settings up to date`);
|
|
161
|
+
this.#logger.info(` Settings up to date`);
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
|
|
@@ -193,7 +195,7 @@ export class KBManager {
|
|
|
193
195
|
|
|
194
196
|
await this.copyBundledFiles(templateDir, dest);
|
|
195
197
|
|
|
196
|
-
logger.info(
|
|
198
|
+
this.#logger.info(
|
|
197
199
|
`Knowledge base initialized at ${dest}\n\nNext steps:\n 1. Edit ${dest}/USER.md with your name, email, and domain\n 2. cd ${dest} && npx apm install\n 3. claude`,
|
|
198
200
|
);
|
|
199
201
|
return { ok: true, value: { dest } };
|
|
@@ -215,7 +217,7 @@ export class KBManager {
|
|
|
215
217
|
};
|
|
216
218
|
}
|
|
217
219
|
await this.copyBundledFiles(templateDir, dest);
|
|
218
|
-
logger.info(`\nKnowledge base updated: ${dest}`);
|
|
220
|
+
this.#logger.info(`\nKnowledge base updated: ${dest}`);
|
|
219
221
|
return { ok: true, value: { dest } };
|
|
220
222
|
}
|
|
221
223
|
|
package/src/outpost.js
CHANGED
|
@@ -22,8 +22,6 @@ import { createCli } from "@forwardimpact/libcli";
|
|
|
22
22
|
import { createLogger } from "@forwardimpact/libtelemetry";
|
|
23
23
|
import { isoTimestamp } from "@forwardimpact/libutil";
|
|
24
24
|
|
|
25
|
-
const logger = createLogger("outpost");
|
|
26
|
-
|
|
27
25
|
import { StateManager } from "./state-manager.js";
|
|
28
26
|
import { AgentRunner } from "./agent-runner.js";
|
|
29
27
|
import { Scheduler, formatLocalTime } from "./scheduler.js";
|
|
@@ -131,6 +129,7 @@ function renderAgentStatus(name, agent, s, kbMissing) {
|
|
|
131
129
|
*/
|
|
132
130
|
export async function run(runtime, version) {
|
|
133
131
|
const { fs, proc, clock } = runtime;
|
|
132
|
+
const logger = createLogger("outpost", runtime);
|
|
134
133
|
|
|
135
134
|
/**
|
|
136
135
|
* Async existence check via the one fs surface this module uses.
|
|
@@ -401,7 +400,7 @@ export async function run(runtime, version) {
|
|
|
401
400
|
}
|
|
402
401
|
|
|
403
402
|
// --- CLI entry point -------------------------------------------------------
|
|
404
|
-
const cli = createCli(buildDefinition(version));
|
|
403
|
+
const cli = createCli(buildDefinition(version), { runtime });
|
|
405
404
|
const parsed = cli.parse(proc.argv.slice(2));
|
|
406
405
|
if (!parsed) return 0;
|
|
407
406
|
|
package/src/scheduler.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* construct further `Date` objects only for deterministic date *arithmetic*
|
|
8
8
|
* over caller-supplied or parsed-from-state inputs (never an ambient no-arg
|
|
9
9
|
* `new Date()`); the AST checker cannot distinguish the two, so this file is
|
|
10
|
-
* allow-listed in
|
|
10
|
+
* allow-listed in .coaligned/invariants/ambient-deps.allow.yml with that reason.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { isoTimestamp } from "@forwardimpact/libutil";
|
package/src/socket-server.js
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
import { createServer } from "node:net";
|
|
6
6
|
import { createConnection } from "node:net";
|
|
7
7
|
import { createLogger } from "@forwardimpact/libtelemetry";
|
|
8
|
-
|
|
9
|
-
const logger = createLogger("outpost");
|
|
10
8
|
import { join, resolve } from "node:path";
|
|
11
9
|
import { homedir } from "node:os";
|
|
12
10
|
import { computeNextWakeAt, nowFromClock } from "./scheduler.js";
|
|
@@ -326,6 +324,7 @@ export class SocketServer {
|
|
|
326
324
|
export async function requestShutdown(socketPath, runtime) {
|
|
327
325
|
if (!runtime?.fsSync) throw new Error("runtime.fsSync is required");
|
|
328
326
|
if (!runtime?.clock) throw new Error("runtime.clock is required");
|
|
327
|
+
const logger = createLogger("outpost", runtime);
|
|
329
328
|
if (!runtime.fsSync.existsSync(socketPath)) {
|
|
330
329
|
logger.info("Daemon not running (no socket).");
|
|
331
330
|
return false;
|