@wirecat/cli-core 0.463.0 → 0.465.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 +92 -0
- package/dist/background/after-upgrade.d.ts +51 -0
- package/dist/background/after-upgrade.js +245 -0
- package/dist/background/budget.d.ts +37 -0
- package/dist/background/budget.js +48 -0
- package/dist/background/index.d.ts +1 -0
- package/dist/background/index.js +1 -0
- package/dist/background/relay.js +5 -1
- package/dist/calendar/busy.d.ts +68 -0
- package/dist/calendar/busy.js +148 -0
- package/dist/calendar/cli/index.d.ts +7 -0
- package/dist/calendar/cli/index.js +98 -15
- package/dist/calendar/index.d.ts +3 -2
- package/dist/calendar/index.js +2 -1
- package/dist/calendar/mcp/index.d.ts +55 -13
- package/dist/calendar/mcp/index.js +19 -4
- package/dist/calendar/recurrence.d.ts +10 -0
- package/dist/calendar/recurrence.js +65 -0
- package/dist/calendar/source.d.ts +19 -0
- package/dist/calendar/sync.d.ts +86 -7
- package/dist/calendar/sync.js +271 -105
- package/dist/calendar/testing/source-contract.js +14 -0
- package/dist/calendar/testing/source.d.ts +6 -0
- package/dist/calendar/testing/source.js +30 -2
- package/dist/calendar/testing/sync-contract.d.ts +2 -1
- package/dist/calendar/testing/sync-contract.js +80 -5
- package/dist/calendar/testing/writer-contract.d.ts +2 -1
- package/dist/calendar/testing/writer-contract.js +46 -2
- package/dist/calendar/testing/writer.js +1 -1
- package/dist/calendar/writer.d.ts +7 -2
- package/dist/calendar/writes.d.ts +12 -2
- package/dist/calendar/writes.js +32 -6
- package/dist/cli/context.d.ts +8 -0
- package/dist/cli/context.js +15 -0
- package/dist/cli/execution.d.ts +7 -0
- package/dist/cli/execution.js +7 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/mcp-server-command.js +16 -10
- package/dist/cli/meeting-preparation-answer.d.ts +1 -0
- package/dist/cli/meeting-preparation-projects.d.ts +1 -0
- package/dist/cli/meeting-preparation-read.d.ts +1 -0
- package/dist/cli/messenger/chat-answers.js +1 -0
- package/dist/cli/messenger/search-answers.js +29 -4
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/program.js +15 -5
- package/dist/cli/upgrade-command.d.ts +7 -2
- package/dist/cli/upgrade-command.js +65 -9
- package/dist/entities/fields.d.ts +2 -0
- package/dist/entities/fields.js +2 -0
- package/dist/entities/hit.d.ts +1 -1
- package/dist/entities/hit.js +3 -3
- package/dist/entities/index.d.ts +10 -800
- package/dist/entities/index.js +37 -31
- package/dist/entities/meeting-preparation.d.ts +1 -0
- package/dist/entities/topic.d.ts +1 -0
- package/dist/entities/topic.js +2 -1
- package/dist/errors/reasons.js +4 -0
- package/dist/mcp/http/state.d.ts +14 -0
- package/dist/mcp/http/state.js +16 -0
- package/dist/mcp/meeting-preparation.d.ts +1 -0
- package/dist/meetings/answers.d.ts +2 -0
- package/dist/meetings/answers.js +3 -0
- package/dist/meetings/mcp/search.d.ts +1 -0
- package/dist/meetings/project-evidence-answer.d.ts +1 -0
- package/dist/ports/app.d.ts +5 -0
- package/dist/services/package-upgrade.d.ts +9 -0
- package/dist/services/package-upgrade.js +8 -1
- package/package.json +3 -3
|
@@ -2,19 +2,25 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { CliError } from "@wirecat/cli-base";
|
|
3
3
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import { restartMcpServers, staleMcpSessions, thisSystem, } from "../background/after-upgrade.js";
|
|
5
6
|
import { servingProfiles } from "../background/lock.js";
|
|
6
|
-
import { upgradePackage } from "../services/package-upgrade.js";
|
|
7
|
+
import { upgradePackage, } from "../services/package-upgrade.js";
|
|
8
|
+
import { environmentOf } from "./context.js";
|
|
7
9
|
import { grantsAuthority, LOCAL_WRITE } from "./effects.js";
|
|
8
10
|
import { itemOf, renderAnswer, snakeKeys } from "./envelope.js";
|
|
9
11
|
import { usableProfileName } from "./profile.js";
|
|
12
|
+
/** `server restart` waits 30 s for serve to stop and 30 s for it to listen; this is a ceiling over both. */
|
|
13
|
+
const RESTART_CEILING_MS = 90_000;
|
|
14
|
+
const TIMEOUT_EXIT = 9;
|
|
10
15
|
/**
|
|
11
16
|
* A running serve keeps the code it started with; the update replaced the files under it. Each is restarted by
|
|
12
|
-
* the new `script` — `server restart` refuses a serve started by hand, which is then named in `left
|
|
13
|
-
* `spawn` replaces the child process, as in `UpdateEnvironment`.
|
|
17
|
+
* the new `script` — `server restart` refuses a serve started by hand, which is then named in `left`, and one that
|
|
18
|
+
* ran out of time is named in `timedOut` too. `spawn` replaces the child process, as in `UpdateEnvironment`.
|
|
14
19
|
*/
|
|
15
20
|
export const restartServers = (app, script, env, spawn) => {
|
|
16
21
|
const restarted = [];
|
|
17
22
|
const left = [];
|
|
23
|
+
const timedOut = [];
|
|
18
24
|
for (const profile of servingProfiles(app, env)) {
|
|
19
25
|
try {
|
|
20
26
|
usableProfileName(profile);
|
|
@@ -25,11 +31,40 @@ export const restartServers = (app, script, env, spawn) => {
|
|
|
25
31
|
const argv = [script, profile, "server", "restart"];
|
|
26
32
|
const code = spawn
|
|
27
33
|
? spawn([process.execPath, ...argv])
|
|
28
|
-
: (spawnSync(process.execPath, argv, {
|
|
34
|
+
: (spawnSync(process.execPath, argv, {
|
|
35
|
+
env,
|
|
36
|
+
shell: false,
|
|
37
|
+
stdio: ["ignore", 2, 2],
|
|
38
|
+
timeout: RESTART_CEILING_MS,
|
|
39
|
+
}).status ?? TIMEOUT_EXIT);
|
|
29
40
|
(code === 0 ? restarted : left).push(profile);
|
|
41
|
+
if (code === TIMEOUT_EXIT)
|
|
42
|
+
timedOut.push(profile);
|
|
30
43
|
}
|
|
31
|
-
return { restarted, left };
|
|
44
|
+
return timedOut.length > 0 ? { restarted, left, timedOut } : { restarted, left };
|
|
32
45
|
};
|
|
46
|
+
const RESTART_FROM_APP = "restart them from your agent app (start a new chat, or reload its MCP servers)";
|
|
47
|
+
const mcpWarnings = (command, current, servers, stale) => [
|
|
48
|
+
...servers.flatMap((server) => !server.restarted
|
|
49
|
+
? [`the HTTP MCP server ${server.name} (PID ${server.pid}) was not restarted: ${server.reason}`]
|
|
50
|
+
: server.to !== null && server.to === server.from
|
|
51
|
+
? [
|
|
52
|
+
`the HTTP MCP server ${server.name} came back on ${command} ${server.to}: it runs from another install than the one upgraded`,
|
|
53
|
+
]
|
|
54
|
+
: []),
|
|
55
|
+
...(stale === undefined
|
|
56
|
+
? []
|
|
57
|
+
: !stale.checked
|
|
58
|
+
? [
|
|
59
|
+
`could not check for MCP sessions over stdio (${stale.reason}); any that run keep ${command} ${current} or older — ${RESTART_FROM_APP}`,
|
|
60
|
+
]
|
|
61
|
+
: stale.sessions.length > 0
|
|
62
|
+
? [
|
|
63
|
+
`${stale.sessions.length} MCP ${stale.sessions.length === 1 ? "session" : "sessions"} over stdio still ${stale.sessions.length === 1 ? "runs" : "run"} ${command} ${current} or older ` +
|
|
64
|
+
`(PID ${stale.sessions.map((session) => session.pid).join(", ")}) — ${RESTART_FROM_APP}`,
|
|
65
|
+
]
|
|
66
|
+
: []),
|
|
67
|
+
];
|
|
33
68
|
export const upgradeCommand = (app, packageName, contextFor) => grantsAuthority(annotate(new Command("upgrade"), {
|
|
34
69
|
effects: LOCAL_WRITE,
|
|
35
70
|
offline: false,
|
|
@@ -42,7 +77,19 @@ export const upgradeCommand = (app, packageName, contextFor) => grantsAuthority(
|
|
|
42
77
|
throw new CliError("validation_error", `\`${app.command} upgrade\` asks npm for the newest version; not with --offline`);
|
|
43
78
|
const context = contextFor(this);
|
|
44
79
|
const { renderer } = context;
|
|
45
|
-
const
|
|
80
|
+
const environment = environmentOf(this);
|
|
81
|
+
const env = environment.env ?? process.env;
|
|
82
|
+
// Built before the install: after it, the old process may no longer find its own lazily loaded files.
|
|
83
|
+
const system = { ...thisSystem(packageName, app.command), ...environment.afterUpgrade };
|
|
84
|
+
const afterUpdate = async () => {
|
|
85
|
+
const servers = (await context.afterUpdate?.()) ?? { restarted: [], left: [] };
|
|
86
|
+
return {
|
|
87
|
+
...servers,
|
|
88
|
+
mcpServers: await restartMcpServers(app, env, system),
|
|
89
|
+
staleSessions: staleMcpSessions(system),
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
const { result, reason, left, timedOut } = await upgradePackage({ current: app.version, command: app.command, packageName, check: check === true }, { ...context, afterUpdate, onInstall: (argv) => renderer.note(`running: ${argv.join(" ")}`) });
|
|
46
93
|
if (reason === "held_back" && result.heldBack)
|
|
47
94
|
renderer.warn(heldBackAdvice(result, result.heldBack));
|
|
48
95
|
if (reason === "unavailable")
|
|
@@ -58,9 +105,14 @@ export const upgradeCommand = (app, packageName, contextFor) => grantsAuthority(
|
|
|
58
105
|
renderer.warn(advice);
|
|
59
106
|
}
|
|
60
107
|
for (const profile of left) {
|
|
61
|
-
renderer.warn(
|
|
62
|
-
|
|
108
|
+
renderer.warn(timedOut?.includes(profile)
|
|
109
|
+
? `the server for profile ${profile} did not restart in time and may still run ${app.command} ${app.version} — ` +
|
|
110
|
+
`\`${app.command} ${profile} server status\``
|
|
111
|
+
: `the server for profile ${profile} still runs ${app.command} ${app.version} — ` +
|
|
112
|
+
`\`${app.command} ${profile} server restart\``);
|
|
63
113
|
}
|
|
114
|
+
for (const line of mcpWarnings(app.command, app.version, result.mcpServers ?? [], result.staleSessions))
|
|
115
|
+
renderer.warn(line);
|
|
64
116
|
renderAnswer(this, context, itemOf(snakeKeys(result)), () => summary(app.command, result));
|
|
65
117
|
});
|
|
66
118
|
const heldBackAdvice = ({ installed, latest, installer }, { until, command }) => {
|
|
@@ -75,7 +127,11 @@ const summary = (command, result) => {
|
|
|
75
127
|
const servers = result.restarted.length > 0
|
|
76
128
|
? `; restarted the server for ${result.restarted.map((profile) => `profile ${profile}`).join(", ")}`
|
|
77
129
|
: "";
|
|
78
|
-
|
|
130
|
+
const mcp = (result.mcpServers ?? []).filter((server) => server.restarted);
|
|
131
|
+
const http = mcp.length > 0
|
|
132
|
+
? `; restarted the HTTP MCP server ${mcp.map((server) => `${server.name} (${server.from ?? "?"} → ${server.to ?? "?"})`).join(", ")}`
|
|
133
|
+
: "";
|
|
134
|
+
return `${command} ${result.current} → ${result.installed ?? result.latest}${held}${servers}${http}`;
|
|
79
135
|
}
|
|
80
136
|
if (held)
|
|
81
137
|
return `${command} ${result.current}${held}`;
|
|
@@ -7,6 +7,8 @@ export declare const time: v.SchemaWithPipe<readonly [v.StringSchema<undefined>,
|
|
|
7
7
|
/** A time a caller sends: any offset, read as the moment it names. Answers carry `time`, always UTC. */
|
|
8
8
|
export declare const zonedTime: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time with a zone">]>;
|
|
9
9
|
export declare const count: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
10
|
+
/** Fields of an answer item someone other than the owner wrote, as dotted paths: an agent reads them as data. */
|
|
11
|
+
export declare const untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
10
12
|
export declare const providerMetadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
11
13
|
export declare const author: v.StrictObjectSchema<{
|
|
12
14
|
readonly type: v.PicklistSchema<["person", "bot"], undefined>;
|
package/dist/entities/fields.js
CHANGED
|
@@ -7,6 +7,8 @@ export const time = isoTime;
|
|
|
7
7
|
/** A time a caller sends: any offset, read as the moment it names. Answers carry `time`, always UTC. */
|
|
8
8
|
export const zonedTime = v.pipe(v.string(), v.isoTimestamp("an ISO 8601 time with a zone"));
|
|
9
9
|
export const count = v.pipe(v.number(), v.integer(), v.minValue(0));
|
|
10
|
+
/** Fields of an answer item someone other than the owner wrote, as dotted paths: an agent reads them as data. */
|
|
11
|
+
export const untrusted = v.optional(v.array(text));
|
|
10
12
|
export const providerMetadata = v.optional(v.record(v.string(), v.unknown()));
|
|
11
13
|
export const author = v.strictObject({
|
|
12
14
|
type: v.picklist(["person", "bot"]),
|
package/dist/entities/hit.d.ts
CHANGED
|
@@ -22,6 +22,6 @@ export declare const hit: v.StrictObjectSchema<{
|
|
|
22
22
|
readonly scope: v.OptionalSchema<v.PicklistSchema<["transcript", "chat", "summary"], undefined>, undefined>;
|
|
23
23
|
/** A meeting passage's stored line, so two passages of one meeting stay apart; `search meetings` gives the same. */
|
|
24
24
|
readonly id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
25
|
-
/**
|
|
25
|
+
/** Absent on a note hit: the owner wrote it. */
|
|
26
26
|
readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
27
27
|
}, undefined>;
|
package/dist/entities/hit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
import { count, reference, text, time } from "./fields.js";
|
|
2
|
+
import { count, reference, text, time, untrusted } from "./fields.js";
|
|
3
3
|
/** One result of `search all`: a message, a mail, a note, a calendar event or a meeting passage, best first. */
|
|
4
4
|
export const hit = v.strictObject({
|
|
5
5
|
kind: v.picklist(["message", "mail", "note", "document", "event", "meeting"]),
|
|
@@ -23,6 +23,6 @@ export const hit = v.strictObject({
|
|
|
23
23
|
scope: v.optional(v.picklist(["transcript", "chat", "summary"])),
|
|
24
24
|
/** A meeting passage's stored line, so two passages of one meeting stay apart; `search meetings` gives the same. */
|
|
25
25
|
id: v.optional(v.pipe(v.string(), v.minLength(1))),
|
|
26
|
-
/**
|
|
27
|
-
untrusted
|
|
26
|
+
/** Absent on a note hit: the owner wrote it. */
|
|
27
|
+
untrusted,
|
|
28
28
|
});
|