@herbertgao/pi-extensions 2026.9.9 → 2026.9.11
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/README.md +1 -0
- package/THIRD_PARTY_NOTICES.md +26 -0
- package/node_modules/@herbertgao/pi-bark/package.json +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -2
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +427 -120
- package/node_modules/@herbertgao/pi-subagents/docs/rpc.md +184 -0
- package/node_modules/@herbertgao/pi-subagents/docs/workflows.md +466 -0
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +6 -6
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/compose.js +52 -0
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/fan-out-audit.js +56 -0
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/gated-fix.js +60 -0
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/lib/count-child.js +30 -0
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/review-panel.js +68 -0
- package/node_modules/@herbertgao/pi-subagents/examples/workflows/structured-findings.js +81 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +12 -10
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +52 -12
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +837 -146
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +213 -39
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +73 -14
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +101 -47
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +2249 -914
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +13 -0
- package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +215 -0
- package/node_modules/@herbertgao/pi-subagents/src/mention.ts +147 -0
- package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +9 -1
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +40 -26
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +18 -8
- package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +46 -9
- package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +21 -16
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +137 -7
- package/node_modules/@herbertgao/pi-subagents/src/structured-output.ts +136 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +126 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-mention.ts +274 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +20 -5
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +10 -4
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +167 -22
- package/node_modules/@herbertgao/pi-subagents/src/ui/workflow-card.ts +555 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/workflow-dialog.ts +1304 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/workflow-menu.ts +226 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/collisions.ts +122 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/entry.ts +47 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/host.ts +463 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/journal.ts +164 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/json-schema.ts +142 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/meta.ts +401 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/progress.ts +622 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/runtime.ts +1399 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/saved.ts +230 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/task.ts +333 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/tool-description.ts +200 -0
- package/node_modules/@herbertgao/pi-subagents/src/workflow/worker-source.ts +781 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +97 -95
- package/node_modules/@herbertgao/pi-subagents/src/xml.ts +13 -0
- package/node_modules/@herbertgao/resume-from/package.json +1 -1
- package/node_modules/@herbertgao/sol-pi/README.md +3 -3
- package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +4 -4
- package/node_modules/@herbertgao/sol-pi/agents-install.md +4 -4
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +6 -6
- package/node_modules/@herbertgao/sol-pi/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/dist/index.ts +39 -89
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +4 -4
- package/node_modules/@narumitw/pi-btw/src/btw.ts +28 -87
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +8 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +40 -37
- package/node_modules/@narumitw/pi-caffeinate/README.md +21 -66
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +10 -41
- package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +2 -2
- package/node_modules/@narumitw/pi-caffeinate/package.json +50 -51
- package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +637 -663
- package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +114 -120
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +29 -29
- package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +108 -126
- package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +124 -128
- package/node_modules/pi-multi-account/CHANGELOG.md +1209 -0
- package/node_modules/pi-multi-account/CONTRIBUTING.md +61 -0
- package/node_modules/pi-multi-account/LICENSE +21 -0
- package/node_modules/pi-multi-account/README.md +197 -0
- package/node_modules/pi-multi-account/SECURITY.md +27 -0
- package/node_modules/pi-multi-account/auth-file-transaction.ts +56 -0
- package/node_modules/pi-multi-account/child-usability.ts +233 -0
- package/node_modules/pi-multi-account/compaction-summary.ts +32 -0
- package/node_modules/pi-multi-account/completion-route-planner.ts +224 -0
- package/node_modules/pi-multi-account/context-guard.ts +420 -0
- package/node_modules/pi-multi-account/cursor/LICENSE +21 -0
- package/node_modules/pi-multi-account/cursor/NOTICE +2 -0
- package/node_modules/pi-multi-account/cursor/auth.ts +165 -0
- package/node_modules/pi-multi-account/cursor/bridge-handle.ts +155 -0
- package/node_modules/pi-multi-account/cursor/conversation-registry.ts +104 -0
- package/node_modules/pi-multi-account/cursor/cursor-models-raw.json +611 -0
- package/node_modules/pi-multi-account/cursor/cursor-shared.ts +192 -0
- package/node_modules/pi-multi-account/cursor/h2-bridge.mjs +175 -0
- package/node_modules/pi-multi-account/cursor/index.ts +572 -0
- package/node_modules/pi-multi-account/cursor/message-parsing.ts +323 -0
- package/node_modules/pi-multi-account/cursor/prompt-usage.ts +53 -0
- package/node_modules/pi-multi-account/cursor/proto/agent_pb.ts +15294 -0
- package/node_modules/pi-multi-account/cursor/proxy.ts +2510 -0
- package/node_modules/pi-multi-account/cursor/session-lifecycle.ts +40 -0
- package/node_modules/pi-multi-account/cursor/sse-keepalive.ts +24 -0
- package/node_modules/pi-multi-account/cursor/stream-lifecycle.ts +193 -0
- package/node_modules/pi-multi-account/cursor/upstream-watchdog.ts +88 -0
- package/node_modules/pi-multi-account/cursor-bridge.ts +240 -0
- package/node_modules/pi-multi-account/cursor-model-name.ts +12 -0
- package/node_modules/pi-multi-account/index.ts +11825 -0
- package/node_modules/pi-multi-account/model-catalog.ts +354 -0
- package/node_modules/pi-multi-account/package.json +101 -0
- package/node_modules/pi-multi-account/pi-contract.ts +281 -0
- package/node_modules/pi-multi-account/provider-payload-stream.ts +44 -0
- package/node_modules/pi-multi-account/provider-priority.ts +189 -0
- package/node_modules/pi-multi-account/slot-proxy-auth.ts +167 -0
- package/node_modules/pi-multi-account/slot-proxy.ts +344 -0
- package/node_modules/pi-multi-account/state-file-transaction.ts +67 -0
- package/node_modules/pi-multi-account/usage.ts +1099 -0
- package/node_modules/pi-typesafe/README.md +6 -2
- package/node_modules/pi-typesafe/dist/client.d.ts +11 -0
- package/node_modules/pi-typesafe/dist/client.js +45 -10
- package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
- package/node_modules/pi-typesafe/dist/index.js +1 -1
- package/node_modules/pi-typesafe/package.json +2 -2
- package/node_modules/pi-web-access/CHANGELOG.md +36 -0
- package/node_modules/pi-web-access/README.md +75 -18
- package/node_modules/pi-web-access/anysearch.ts +4 -15
- package/node_modules/pi-web-access/bocha.ts +3 -22
- package/node_modules/pi-web-access/brave.ts +3 -21
- package/node_modules/pi-web-access/brightdata.ts +5 -32
- package/node_modules/pi-web-access/content-find.ts +168 -53
- package/node_modules/pi-web-access/curator-page.ts +4 -1
- package/node_modules/pi-web-access/curator-run.ts +2 -1
- package/node_modules/pi-web-access/curator-server.ts +1 -0
- package/node_modules/pi-web-access/dist/index.js +24620 -0
- package/node_modules/pi-web-access/domain-filter-normalization.ts +14 -0
- package/node_modules/pi-web-access/duckduckgo.ts +3 -21
- package/node_modules/pi-web-access/extract.ts +3 -1
- package/node_modules/pi-web-access/firecrawl.ts +5 -29
- package/node_modules/pi-web-access/gemini-search.ts +81 -32
- package/node_modules/pi-web-access/index.ts +149 -148
- package/node_modules/pi-web-access/jina-search.ts +4 -15
- package/node_modules/pi-web-access/kagi.ts +4 -13
- package/node_modules/pi-web-access/kimi-search.ts +5 -30
- package/node_modules/pi-web-access/mistral-search.ts +1 -15
- package/node_modules/pi-web-access/ollama.ts +2 -7
- package/node_modules/pi-web-access/openai-search.ts +174 -36
- package/node_modules/pi-web-access/opencode-session-headers.ts +24 -0
- package/node_modules/pi-web-access/package.json +10 -4
- package/node_modules/pi-web-access/page-query.ts +10 -2
- package/node_modules/pi-web-access/parallel.ts +1 -15
- package/node_modules/pi-web-access/pdf-extract.ts +3 -0
- package/node_modules/pi-web-access/querit.ts +5 -29
- package/node_modules/pi-web-access/search-answer-formatting.ts +11 -0
- package/node_modules/pi-web-access/search-result-count-normalization.ts +4 -0
- package/node_modules/pi-web-access/search1api.ts +5 -29
- package/node_modules/pi-web-access/searchinfinity.ts +5 -29
- package/node_modules/pi-web-access/searxng.ts +3 -21
- package/node_modules/pi-web-access/serpapi.ts +5 -28
- package/node_modules/pi-web-access/serpbase.ts +3 -22
- package/node_modules/pi-web-access/serpdive.ts +3 -21
- package/node_modules/pi-web-access/serper.ts +5 -28
- package/node_modules/pi-web-access/serply.ts +197 -0
- package/node_modules/pi-web-access/source-check.ts +11 -47
- package/node_modules/pi-web-access/summary-review.ts +7 -3
- package/node_modules/pi-web-access/tavily.ts +3 -21
- package/node_modules/pi-web-access/tinyfish.ts +5 -29
- package/node_modules/pi-web-access/utils.ts +9 -1
- package/node_modules/pi-web-access/valyu.ts +5 -28
- package/node_modules/pi-web-access/xai-search.ts +1 -15
- package/node_modules/pi-web-access/xcrawl.ts +5 -32
- package/package.json +17 -11
|
@@ -11,192 +11,188 @@ const LEGACY_SETTINGS_FILE = "pi-caffeinate-settings.json";
|
|
|
11
11
|
export type CaffeinateMode = "sleep" | "display";
|
|
12
12
|
|
|
13
13
|
export interface CaffeinateSettings {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
mode: CaffeinateMode;
|
|
15
|
+
quiet: boolean;
|
|
16
|
+
updatedAt: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface SettingsFileOperations {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
write(path: string, data: string): Promise<void>;
|
|
21
|
+
rename(source: string, destination: string): Promise<void>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const DEFAULT_FILE_OPERATIONS: SettingsFileOperations = {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
write: (path, data) => writeFile(path, data, "utf8").then(() => undefined),
|
|
26
|
+
rename,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export type SettingsLoadResult =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
| { kind: "missing"; notice?: string }
|
|
31
|
+
| { kind: "invalid"; reason: string; notice?: string }
|
|
32
|
+
| { kind: "loaded"; settings: CaffeinateSettings; notice?: string };
|
|
33
33
|
|
|
34
34
|
export async function loadSettings(): Promise<SettingsLoadResult> {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
await settingsSaveQueue;
|
|
36
|
+
const newPath = settingsFilePath();
|
|
37
|
+
const newSettings = await readSettingsFile(newPath);
|
|
38
|
+
if (newSettings.kind !== "missing") return withLegacyIgnoredNotice(newSettings);
|
|
39
|
+
|
|
40
|
+
const legacyPath = legacySettingsFilePath();
|
|
41
|
+
const legacySettings = await readSettingsFile(legacyPath);
|
|
42
|
+
const concurrentlyCreatedSettings = await readSettingsFile(newPath);
|
|
43
|
+
if (concurrentlyCreatedSettings.kind !== "missing") {
|
|
44
|
+
return withLegacyIgnoredNotice(concurrentlyCreatedSettings);
|
|
45
|
+
}
|
|
46
|
+
if (legacySettings.kind === "missing") return { kind: "missing" };
|
|
47
|
+
if (legacySettings.kind === "invalid") return legacySettings;
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
...legacySettings,
|
|
51
|
+
notice: `Using legacy ${LEGACY_SETTINGS_FILE}; rename it to ${NEW_SETTINGS_FILE}. Future saves write ${NEW_SETTINGS_FILE} without modifying the legacy file.`,
|
|
52
|
+
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
interface SettingsDocumentResult {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
result: SettingsLoadResult;
|
|
57
|
+
document?: Record<string, unknown>;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function readSettingsDocument(filePath: string): Promise<SettingsDocumentResult> {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
61
|
+
let text: string;
|
|
62
|
+
try {
|
|
63
|
+
text = await readFile(filePath, "utf8");
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (isNodeError(error) && error.code === "ENOENT") return { result: { kind: "missing" } };
|
|
66
|
+
return { result: { kind: "invalid", reason: `${filePath}: ${formatError(error)}` } };
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const document = JSON.parse(text) as unknown;
|
|
70
|
+
const settings = normalizeCaffeinateSettings(document);
|
|
71
|
+
if (settings) {
|
|
72
|
+
return {
|
|
73
|
+
result: { kind: "loaded", settings },
|
|
74
|
+
document: { ...(document as Record<string, unknown>) },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
result: {
|
|
79
|
+
kind: "invalid",
|
|
80
|
+
reason: `${filePath}: expected { "mode": "sleep" | "display", optional "quiet": boolean }`,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return { result: { kind: "invalid", reason: `${filePath}: ${formatError(error)}` } };
|
|
85
|
+
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
async function readSettingsFile(filePath: string): Promise<SettingsLoadResult> {
|
|
89
|
-
|
|
89
|
+
return (await readSettingsDocument(filePath)).result;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async function withLegacyIgnoredNotice(settings: SettingsLoadResult): Promise<SettingsLoadResult> {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
if (!(await fileExists(legacySettingsFilePath()))) return settings;
|
|
94
|
+
return {
|
|
95
|
+
...settings,
|
|
96
|
+
notice: `pi-caffeinate legacy settings ignored: ${legacySettingsFilePath()} exists, but ${settingsFilePath()} takes precedence. Delete ${LEGACY_SETTINGS_FILE} after confirming your settings.`,
|
|
97
|
+
};
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
async function fileExists(filePath: string) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
try {
|
|
102
|
+
await access(filePath, constants.F_OK);
|
|
103
|
+
return true;
|
|
104
|
+
} catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
async function pathEntryExists(filePath: string) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
try {
|
|
111
|
+
await lstat(filePath);
|
|
112
|
+
return true;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (isNodeError(error) && error.code === "ENOENT") return false;
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
export function normalizeCaffeinateSettings(value: unknown): CaffeinateSettings | undefined {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
if (!value || typeof value !== "object") return undefined;
|
|
121
|
+
const settings = value as { mode?: unknown; quiet?: unknown; updatedAt?: unknown };
|
|
122
|
+
if (!isCaffeinateMode(settings.mode)) return undefined;
|
|
123
|
+
if (settings.quiet !== undefined && typeof settings.quiet !== "boolean") return undefined;
|
|
124
|
+
if (settings.updatedAt !== undefined && typeof settings.updatedAt !== "number") return undefined;
|
|
125
|
+
return {
|
|
126
|
+
mode: settings.mode,
|
|
127
|
+
quiet: settings.quiet ?? false,
|
|
128
|
+
updatedAt: settings.updatedAt ?? 0,
|
|
129
|
+
};
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
function isCaffeinateMode(value: unknown): value is CaffeinateMode {
|
|
133
|
-
|
|
133
|
+
return value === "sleep" || value === "display";
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
let settingsSaveQueue: Promise<unknown> = Promise.resolve();
|
|
137
137
|
|
|
138
138
|
export function saveSettings(
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
settings: Omit<CaffeinateSettings, "quiet"> & { quiet?: boolean },
|
|
140
|
+
operations: Partial<SettingsFileOperations> = {},
|
|
141
141
|
): Promise<CaffeinateSettings> {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
const operation = settingsSaveQueue.then(() => saveSettingsNow(settings, operations));
|
|
143
|
+
settingsSaveQueue = operation.catch(() => undefined);
|
|
144
|
+
return operation;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
async function saveSettingsNow(
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
settings: Omit<CaffeinateSettings, "quiet"> & { quiet?: boolean },
|
|
149
|
+
operations: Partial<SettingsFileOperations>,
|
|
150
150
|
): Promise<CaffeinateSettings> {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
} catch (error) {
|
|
179
|
-
await rm(tempFile, { force: true }).catch(() => undefined);
|
|
180
|
-
throw error;
|
|
181
|
-
}
|
|
151
|
+
const filePath = settingsFilePath();
|
|
152
|
+
let current = await readSettingsDocument(filePath);
|
|
153
|
+
const replaceCanonical = current.result.kind !== "missing";
|
|
154
|
+
if (!replaceCanonical) current = await readSettingsDocument(legacySettingsFilePath());
|
|
155
|
+
if (current.result.kind === "invalid") {
|
|
156
|
+
throw new Error(`Cannot save pi-caffeinate settings until you repair ${current.result.reason}`);
|
|
157
|
+
}
|
|
158
|
+
const document = current.document ?? {};
|
|
159
|
+
const quiet = settings.quiet ?? (current.result.kind === "loaded" ? current.result.settings.quiet : false);
|
|
160
|
+
const nextSettings = { mode: settings.mode, quiet, updatedAt: settings.updatedAt };
|
|
161
|
+
const nextDocument = {
|
|
162
|
+
...document,
|
|
163
|
+
...nextSettings,
|
|
164
|
+
};
|
|
165
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
166
|
+
const tempFile = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
167
|
+
try {
|
|
168
|
+
await (operations.write ?? DEFAULT_FILE_OPERATIONS.write)(tempFile, `${JSON.stringify(nextDocument, null, 2)}\n`);
|
|
169
|
+
if (!replaceCanonical && (await pathEntryExists(filePath))) {
|
|
170
|
+
throw new Error(`${NEW_SETTINGS_FILE} was created concurrently; reopen settings and retry.`);
|
|
171
|
+
}
|
|
172
|
+
await (operations.rename ?? DEFAULT_FILE_OPERATIONS.rename)(tempFile, filePath);
|
|
173
|
+
return nextSettings;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
await rm(tempFile, { force: true }).catch(() => undefined);
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
182
178
|
}
|
|
183
179
|
|
|
184
180
|
export function settingsFilePath() {
|
|
185
|
-
|
|
181
|
+
return join(agentDir(), NEW_SETTINGS_FILE);
|
|
186
182
|
}
|
|
187
183
|
|
|
188
184
|
function legacySettingsFilePath() {
|
|
189
|
-
|
|
185
|
+
return join(agentDir(), LEGACY_SETTINGS_FILE);
|
|
190
186
|
}
|
|
191
187
|
|
|
192
188
|
function agentDir() {
|
|
193
|
-
|
|
189
|
+
return getAgentDir();
|
|
194
190
|
}
|
|
195
191
|
|
|
196
192
|
function isNodeError(error: unknown): error is NodeJS.ErrnoException {
|
|
197
|
-
|
|
193
|
+
return error instanceof Error && "code" in error;
|
|
198
194
|
}
|
|
199
195
|
|
|
200
196
|
function formatError(error: unknown) {
|
|
201
|
-
|
|
197
|
+
return error instanceof Error ? error.message : String(error);
|
|
202
198
|
}
|