@gajae-code/coding-agent 0.11.6 → 0.11.8
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/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-activation.d.ts +4 -3
- package/dist/types/config/model-profile-contract.d.ts +38 -0
- package/dist/types/config/settings-schema.d.ts +70 -7
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/gjc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +20 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/main.d.ts +32 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
- package/dist/types/modes/interactive-mode.d.ts +7 -2
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +4 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +26 -1
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +105 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +18 -3
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +189 -4
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +1 -1
- package/dist/types/sdk/host/query/handlers.d.ts +9 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/startup-capability.d.ts +3 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +30 -5
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +32 -9
- package/dist/types/session/internal/managed-session-storage.d.ts +27 -10
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/session-manager.d.ts +25 -4
- package/dist/types/session/session-storage.d.ts +18 -0
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +94 -0
- package/dist/types/tools/ask.d.ts +454 -174
- package/dist/types/tools/fetch.d.ts +5 -8
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -8
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-sdk-operation-inventory.ts +4 -0
- package/scripts/run-test-manifest.ts +4 -4
- package/src/capability/index.ts +50 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +2 -92
- package/src/cli/notify-cli.ts +5 -38
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +52 -9
- package/src/commands/daemon.ts +22 -5
- package/src/commands/sdk.ts +44 -11
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-activation.ts +7 -18
- package/src/config/model-profile-contract.ts +161 -0
- package/src/config/model-profiles.ts +18 -0
- package/src/config/model-registry.ts +11 -1
- package/src/config/settings-schema.ts +73 -7
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +2 -2
- package/src/defaults/gjc/skills/ralplan/SKILL.md +3 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +42 -1
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/py/executor.ts +30 -11
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +2 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/gjc-runtime/launch-tmux.ts +1 -1
- package/src/gjc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/gjc-runtime/ralplan-runtime.ts +75 -3
- package/src/gjc-runtime/repository-binding.ts +267 -0
- package/src/gjc-runtime/session-state-sidecar.ts +25 -9
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -1
- package/src/gjc-runtime/tmux-sessions.ts +45 -6
- package/src/gjc-runtime/ultragoal-guard.ts +93 -15
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +103 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +456 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +23 -0
- package/src/internal-urls/docs-index.generated.ts +12 -10
- package/src/internal-urls/local-protocol.ts +64 -21
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +111 -37
- package/src/modes/DESIGN.md +5 -0
- package/src/modes/acp/acp-agent.ts +50 -16
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/model-selector.ts +73 -11
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/tool-status-header.ts +25 -4
- package/src/modes/components/welcome.ts +22 -18
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +97 -54
- package/src/modes/controllers/event-controller.ts +10 -0
- package/src/modes/controllers/input-controller.ts +38 -2
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +149 -63
- package/src/modes/interactive-mode.ts +57 -34
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +4 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +5 -3
- package/src/prompts/agents/architect.md +0 -1
- package/src/prompts/agents/critic.md +0 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -4
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/json-rpc.ts +23 -9
- package/src/runtime-mcp/manager.ts +51 -53
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/lifecycle.ts +185 -36
- package/src/sdk/bus/chat-daemon-control.ts +19 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +9 -1
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/index.ts +244 -70
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +68 -20
- package/src/sdk/bus/prompt-reconciliation.ts +239 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/telegram-daemon-contract.ts +18 -3
- package/src/sdk/bus/telegram-daemon-control.ts +147 -35
- package/src/sdk/bus/telegram-daemon.ts +2463 -450
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +1 -1
- package/src/sdk/host/control/operations.ts +1 -1
- package/src/sdk/host/host.ts +2 -6
- package/src/sdk/host/query/handlers.ts +70 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +58 -0
- package/src/sdk/protocol/operation-registry.ts +18 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +31 -5
- package/src/sdk/startup-capability.ts +9 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +292 -154
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/internal/managed-session-scope.ts +1163 -137
- package/src/session/internal/managed-session-storage.ts +397 -234
- package/src/session/internal/native-publish-outcome.ts +266 -0
- package/src/session/session-manager.ts +620 -403
- package/src/session/session-storage.ts +128 -11
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +30 -1
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/gjc-command.ts +2 -2
- package/src/task/index.ts +121 -15
- package/src/task/receipt.ts +3 -0
- package/src/task/types.ts +34 -3
- package/src/tools/ask.ts +199 -89
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +13 -131
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +4 -0
- package/src/tools/read.ts +2 -0
- package/src/tools/render-utils.ts +7 -1
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product-surface dogfood for #2901 repository binding.
|
|
3
|
+
*
|
|
4
|
+
* Creates two sibling git repos, runs real `gjc ultragoal` / `gjc ralplan`
|
|
5
|
+
* CLI entrypoints from source, and prints fail-closed mismatch evidence.
|
|
6
|
+
*
|
|
7
|
+
* Usage (from monorepo root):
|
|
8
|
+
* bun packages/coding-agent/scripts/dogfood-repository-binding.ts
|
|
9
|
+
*/
|
|
10
|
+
import * as fsp from "node:fs/promises";
|
|
11
|
+
import * as os from "node:os";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import {
|
|
15
|
+
assertCwdMatchesRepositoryBinding,
|
|
16
|
+
assertPathUnderRepositoryBinding,
|
|
17
|
+
parseRepositoryBinding,
|
|
18
|
+
resolveTaskRepositoryBinding,
|
|
19
|
+
} from "../src/gjc-runtime/repository-binding";
|
|
20
|
+
import { readUltragoalPlan, startNextUltragoalGoal } from "../src/gjc-runtime/ultragoal-runtime";
|
|
21
|
+
|
|
22
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
23
|
+
const cli = path.join(repoRoot, "packages/coding-agent/src/cli.ts");
|
|
24
|
+
|
|
25
|
+
async function runGit(cwd: string, args: string[]): Promise<void> {
|
|
26
|
+
const proc = Bun.spawn(["git", ...args], { cwd, stdout: "pipe", stderr: "pipe" });
|
|
27
|
+
const code = await proc.exited;
|
|
28
|
+
if (code !== 0) throw new Error(`git ${args.join(" ")} failed: ${await new Response(proc.stderr).text()}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function initRepo(root: string): Promise<void> {
|
|
32
|
+
await fsp.mkdir(root, { recursive: true });
|
|
33
|
+
await runGit(root, ["init"]);
|
|
34
|
+
await runGit(root, ["config", "user.email", "dogfood@example.com"]);
|
|
35
|
+
await runGit(root, ["config", "user.name", "Dogfood"]);
|
|
36
|
+
await fsp.writeFile(path.join(root, "README.md"), `repo ${path.basename(root)}\n`);
|
|
37
|
+
await runGit(root, ["add", "README.md"]);
|
|
38
|
+
await runGit(root, ["commit", "-m", `init ${path.basename(root)}`]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function runCli(
|
|
42
|
+
cwd: string,
|
|
43
|
+
args: string[],
|
|
44
|
+
env: NodeJS.ProcessEnv,
|
|
45
|
+
): Promise<{ code: number; stdout: string; stderr: string }> {
|
|
46
|
+
const proc = Bun.spawn(["bun", cli, ...args], { cwd, env, stdout: "pipe", stderr: "pipe" });
|
|
47
|
+
const [code, stdout, stderr] = await Promise.all([
|
|
48
|
+
proc.exited,
|
|
49
|
+
new Response(proc.stdout).text(),
|
|
50
|
+
new Response(proc.stderr).text(),
|
|
51
|
+
]);
|
|
52
|
+
return { code, stdout, stderr };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main(): Promise<void> {
|
|
56
|
+
const dogfoodRoot = await fsp.mkdtemp(path.join(os.tmpdir(), "gjc-dogfood-2901-"));
|
|
57
|
+
const left = path.join(dogfoodRoot, "gajae-code");
|
|
58
|
+
const right = path.join(dogfoodRoot, "oh-my-openagent-senpi");
|
|
59
|
+
await initRepo(left);
|
|
60
|
+
await initRepo(right);
|
|
61
|
+
|
|
62
|
+
const sessionId = `dogfood-2901-${process.pid}`;
|
|
63
|
+
const env = { ...process.env, GJC_SESSION_ID: sessionId };
|
|
64
|
+
|
|
65
|
+
console.log("# Dogfood: repository binding (#2901)");
|
|
66
|
+
console.log(`root=${dogfoodRoot}`);
|
|
67
|
+
console.log(`left=${left}`);
|
|
68
|
+
console.log(`right=${right}`);
|
|
69
|
+
console.log(`session=${sessionId}`);
|
|
70
|
+
console.log(`cli=${cli}`);
|
|
71
|
+
console.log(`bun=${Bun.version}`);
|
|
72
|
+
console.log(
|
|
73
|
+
`commit=${Bun.spawnSync(["git", "-C", repoRoot, "rev-parse", "--short", "HEAD"]).stdout.toString().trim()}`,
|
|
74
|
+
);
|
|
75
|
+
console.log();
|
|
76
|
+
|
|
77
|
+
// 1) Product CLI: create goals stamps binding
|
|
78
|
+
const create = await runCli(
|
|
79
|
+
left,
|
|
80
|
+
[
|
|
81
|
+
"ultragoal",
|
|
82
|
+
"create-goals",
|
|
83
|
+
"--brief",
|
|
84
|
+
"@goal dogfood binding\nProve repository binding stamps and fail-closed sibling mismatch.",
|
|
85
|
+
"--json",
|
|
86
|
+
],
|
|
87
|
+
env,
|
|
88
|
+
);
|
|
89
|
+
console.log("## 1) gjc ultragoal create-goals (LEFT)");
|
|
90
|
+
console.log(`exit=${create.code}`);
|
|
91
|
+
console.log(create.stdout.trim() || create.stderr.trim());
|
|
92
|
+
if (create.code !== 0) process.exit(1);
|
|
93
|
+
|
|
94
|
+
const plan = await readUltragoalPlan(left, sessionId);
|
|
95
|
+
if (!plan?.repositoryBinding) {
|
|
96
|
+
console.error("FAIL: plan missing repositoryBinding");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
console.log();
|
|
100
|
+
console.log("## 2) goals.json repositoryBinding");
|
|
101
|
+
console.log(JSON.stringify(plan.repositoryBinding, null, 2));
|
|
102
|
+
|
|
103
|
+
// 2) Matching cwd starts goal
|
|
104
|
+
console.log();
|
|
105
|
+
console.log("## 3) startNextUltragoalGoal on LEFT (match)");
|
|
106
|
+
const started = await startNextUltragoalGoal({ cwd: left, sessionId });
|
|
107
|
+
console.log(`ok goal=${started.goal?.id} status=${started.goal?.status}`);
|
|
108
|
+
|
|
109
|
+
// 3) Sibling mismatch fails closed
|
|
110
|
+
console.log();
|
|
111
|
+
console.log("## 4) assertCwdMatchesRepositoryBinding on RIGHT (sibling)");
|
|
112
|
+
try {
|
|
113
|
+
await assertCwdMatchesRepositoryBinding(right, plan.repositoryBinding);
|
|
114
|
+
console.error("FAIL: expected identity_mismatch");
|
|
115
|
+
process.exit(1);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.log(`fail_closed: ${error instanceof Error ? error.message : String(error)}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 4) Path escape fails closed
|
|
121
|
+
console.log();
|
|
122
|
+
console.log("## 5) assertPathUnderRepositoryBinding sibling absolute path");
|
|
123
|
+
try {
|
|
124
|
+
assertPathUnderRepositoryBinding(plan.repositoryBinding, path.join(right, "README.md"));
|
|
125
|
+
console.error("FAIL: expected path_outside_root");
|
|
126
|
+
process.exit(1);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.log(`fail_closed: ${error instanceof Error ? error.message : String(error)}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 5) Task binding stamp + sibling fail-closed (pre-discovery authority)
|
|
132
|
+
console.log();
|
|
133
|
+
console.log("## 6) task binding stamp (omit declaration) + sibling reject");
|
|
134
|
+
const stamped = await resolveTaskRepositoryBinding(left, undefined);
|
|
135
|
+
console.log(`stamped_worktreeRoot=${stamped.worktreeRoot}`);
|
|
136
|
+
await assertCwdMatchesRepositoryBinding(left, stamped);
|
|
137
|
+
console.log("task_stamp_ok on LEFT");
|
|
138
|
+
const taskBinding = parseRepositoryBinding(plan.repositoryBinding);
|
|
139
|
+
try {
|
|
140
|
+
await resolveTaskRepositoryBinding(right, taskBinding);
|
|
141
|
+
console.error("FAIL: task binding should reject RIGHT");
|
|
142
|
+
process.exit(1);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.log(`task_binding_fail_closed on RIGHT: ${error instanceof Error ? error.message : String(error)}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 6) Ralplan seed stamps binding via product CLI
|
|
148
|
+
console.log();
|
|
149
|
+
console.log("## 7) gjc ralplan seed (LEFT)");
|
|
150
|
+
const ralplan = await runCli(left, ["ralplan", "--json", "dogfood multi-repo binding"], env);
|
|
151
|
+
console.log(`exit=${ralplan.code}`);
|
|
152
|
+
console.log(ralplan.stdout.trim() || ralplan.stderr.trim());
|
|
153
|
+
if (ralplan.code !== 0) process.exit(1);
|
|
154
|
+
const statePath = path.join(left, ".gjc", `_session-${sessionId}`, "state", "ralplan-state.json");
|
|
155
|
+
const state = JSON.parse(await fsp.readFile(statePath, "utf8")) as {
|
|
156
|
+
repository_binding?: unknown;
|
|
157
|
+
run_id?: string;
|
|
158
|
+
};
|
|
159
|
+
console.log();
|
|
160
|
+
console.log("## 8) ralplan-state.json repository_binding");
|
|
161
|
+
console.log(JSON.stringify({ run_id: state.run_id, repository_binding: state.repository_binding }, null, 2));
|
|
162
|
+
if (!state.repository_binding) {
|
|
163
|
+
console.error("FAIL: ralplan state missing repository_binding");
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 7) Ralplan stage write on LEFT succeeds and echoes repository_binding
|
|
168
|
+
console.log();
|
|
169
|
+
console.log("## 9) gjc ralplan --write planner on LEFT (match)");
|
|
170
|
+
const notePath = path.join(left, "dogfood-planner.md");
|
|
171
|
+
await fsp.writeFile(notePath, "# dogfood planner\n");
|
|
172
|
+
const writeLeft = await runCli(
|
|
173
|
+
left,
|
|
174
|
+
["ralplan", "--write", "--stage", "planner", "--stage_n", "1", "--artifact", notePath, "--json"],
|
|
175
|
+
env,
|
|
176
|
+
);
|
|
177
|
+
console.log(`exit=${writeLeft.code}`);
|
|
178
|
+
console.log(writeLeft.stdout.trim() || writeLeft.stderr.trim());
|
|
179
|
+
if (writeLeft.code !== 0) process.exit(1);
|
|
180
|
+
const writePayload = JSON.parse(writeLeft.stdout) as { repository_binding?: { worktreeRoot?: string } };
|
|
181
|
+
if (!writePayload.repository_binding?.worktreeRoot) {
|
|
182
|
+
console.error("FAIL: write receipt missing repository_binding");
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 8) Copy seed authority into RIGHT session layout → stage write fails closed
|
|
187
|
+
console.log();
|
|
188
|
+
console.log("## 10) ralplan --write on RIGHT with LEFT binding (fail-closed)");
|
|
189
|
+
const rightStateDir = path.join(right, ".gjc", `_session-${sessionId}`, "state");
|
|
190
|
+
await fsp.mkdir(rightStateDir, { recursive: true });
|
|
191
|
+
await fsp.copyFile(statePath, path.join(rightStateDir, "ralplan-state.json"));
|
|
192
|
+
const writeRight = await runCli(
|
|
193
|
+
right,
|
|
194
|
+
["ralplan", "--write", "--stage", "architect", "--stage_n", "1", "--artifact", "# arch\n", "--json"],
|
|
195
|
+
env,
|
|
196
|
+
);
|
|
197
|
+
console.log(`exit=${writeRight.code}`);
|
|
198
|
+
console.log((writeRight.stderr || writeRight.stdout).trim());
|
|
199
|
+
if (writeRight.code === 0) {
|
|
200
|
+
console.error("FAIL: expected sibling write to fail closed");
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
console.log("fail_closed: ralplan write on sibling rejected");
|
|
204
|
+
|
|
205
|
+
console.log();
|
|
206
|
+
console.log("DOGFOOD_OK");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await main();
|
|
@@ -39,6 +39,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
39
39
|
"agent_session:setForcedToolChoice": "internal accessor/plumbing, not a user-facing control seam",
|
|
40
40
|
"agent_session:getActiveSkillState": "internal accessor/plumbing, not a user-facing control seam",
|
|
41
41
|
"agent_session:getActiveSkillPhase": "internal accessor/plumbing, not a user-facing control seam",
|
|
42
|
+
"agent_session:getDeepInterviewAskStage":
|
|
43
|
+
"internal AskTool schema-selection accessor, not a user-facing SDK control seam",
|
|
42
44
|
"agent_session:peekQueueInvoker": "internal accessor/plumbing, not a user-facing control seam",
|
|
43
45
|
"agent_session:peekStandingResolveHandler": "internal accessor/plumbing, not a user-facing control seam",
|
|
44
46
|
"agent_session:setStandingResolveHandler": "internal accessor/plumbing, not a user-facing control seam",
|
|
@@ -147,6 +149,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
147
149
|
"agent_session:prepareContributionPrep": "internal accessor/plumbing, not a user-facing control seam",
|
|
148
150
|
"agent_session:setResourceSampler": "internal accessor/plumbing, not a user-facing control seam",
|
|
149
151
|
"agent_session:setRetainedMemorySampler": "internal accessor/plumbing, not a user-facing control seam",
|
|
152
|
+
"agent_session:createBtwConversationScope":
|
|
153
|
+
"internal privacy-scoped side-chat snapshot factory, not a user-facing SDK control seam",
|
|
150
154
|
"agent_session:recordBashResult": "internal accessor/plumbing, not a user-facing control seam",
|
|
151
155
|
"agent_session:executePython": "internal accessor/plumbing, not a user-facing control seam",
|
|
152
156
|
"agent_session:assertEvalExecutionAllowed": "internal accessor/plumbing, not a user-facing control seam",
|
|
@@ -60,11 +60,11 @@ function validateRowReceipts(rows: ManifestAdapterRow[]): void {
|
|
|
60
60
|
}
|
|
61
61
|
counts.set(row.adapter, (counts.get(row.adapter) ?? 0) + 1);
|
|
62
62
|
}
|
|
63
|
-
if (rows.length !== ADAPTERS.length *
|
|
64
|
-
throw new Error(`Expected ${ADAPTERS.length *
|
|
63
|
+
if (rows.length !== ADAPTERS.length * 93)
|
|
64
|
+
throw new Error(`Expected ${ADAPTERS.length * 93} adapter rows; received ${rows.length}.`);
|
|
65
65
|
for (const adapter of ADAPTERS) {
|
|
66
|
-
if (counts.get(adapter) !==
|
|
67
|
-
throw new Error(`Expected
|
|
66
|
+
if (counts.get(adapter) !== 93)
|
|
67
|
+
throw new Error(`Expected 93 ${adapter} rows; received ${counts.get(adapter) ?? 0}.`);
|
|
68
68
|
}
|
|
69
69
|
process.stdout.write(
|
|
70
70
|
`manifest check: ${rows.length} row receipts (${[...counts].map(([adapter, count]) => `${adapter}=${count}`).join(", ")})\n`,
|
package/src/capability/index.ts
CHANGED
|
@@ -41,6 +41,8 @@ const disabledProviders = new Set<string>();
|
|
|
41
41
|
|
|
42
42
|
/** Settings manager for persistence (if set) */
|
|
43
43
|
let settings: Settings | null = null;
|
|
44
|
+
/** Session-local settings keyed by normalized working directory. */
|
|
45
|
+
const settingsByCwd = new Map<string, Settings>();
|
|
44
46
|
|
|
45
47
|
// =============================================================================
|
|
46
48
|
// Registration API
|
|
@@ -208,8 +210,9 @@ async function loadImpl<T>(
|
|
|
208
210
|
* Filter providers based on options and disabled state.
|
|
209
211
|
*/
|
|
210
212
|
function filterProviders<T>(capability: Capability<T>, options: LoadOptions): Provider<T>[] {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
const activeSettings = options.settings ?? settingsByCwd.get(path.normalize(options.cwd ?? getProjectDir()));
|
|
214
|
+
const activeDisabledProviders = new Set(activeSettings?.get("disabledProviders") ?? disabledProviders);
|
|
215
|
+
let providers = (capability.providers as Provider<T>[]).filter(p => !activeDisabledProviders.has(p.id));
|
|
213
216
|
if (options.providers) {
|
|
214
217
|
const allowed = new Set(options.providers);
|
|
215
218
|
providers = providers.filter(p => allowed.has(p.id));
|
|
@@ -249,63 +252,68 @@ export async function loadCapability<T>(capabilityId: string, options: LoadOptio
|
|
|
249
252
|
* Call this once on startup to enable persistent provider state.
|
|
250
253
|
*/
|
|
251
254
|
export function initializeWithSettings(activeSettings: Settings): void {
|
|
255
|
+
settingsByCwd.set(path.normalize(activeSettings.getCwd()), activeSettings);
|
|
252
256
|
settings = activeSettings;
|
|
253
|
-
|
|
254
|
-
const disabled = settings.get("disabledProviders");
|
|
257
|
+
const disabled = activeSettings.get("disabledProviders");
|
|
255
258
|
disabledProviders.clear();
|
|
256
|
-
for (const id of disabled)
|
|
257
|
-
disabledProviders.add(id);
|
|
258
|
-
}
|
|
259
|
+
for (const id of disabled) disabledProviders.add(id);
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
/**
|
|
262
263
|
* Persist current disabled providers to settings.
|
|
263
264
|
*/
|
|
264
|
-
function persistDisabledProviders(): void {
|
|
265
|
-
|
|
266
|
-
settings.set("disabledProviders", Array.from(disabledProviders));
|
|
267
|
-
}
|
|
265
|
+
function persistDisabledProviders(activeSettings: Settings, providers: ReadonlySet<string>): void {
|
|
266
|
+
activeSettings.set("disabledProviders", Array.from(providers));
|
|
268
267
|
}
|
|
269
268
|
|
|
270
|
-
/**
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
269
|
+
/** Disable a provider for the supplied session settings. */
|
|
270
|
+
export function disableProvider(
|
|
271
|
+
providerId: string,
|
|
272
|
+
activeSettings: Settings = settings ??
|
|
273
|
+
(() => {
|
|
274
|
+
throw new Error("Capability settings unavailable");
|
|
275
|
+
})(),
|
|
276
|
+
): void {
|
|
277
|
+
const providers = new Set(activeSettings.get("disabledProviders"));
|
|
278
|
+
providers.add(providerId);
|
|
279
|
+
persistDisabledProviders(activeSettings, providers);
|
|
276
280
|
}
|
|
277
281
|
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
/** Enable a provider for the supplied session settings. */
|
|
283
|
+
export function enableProvider(
|
|
284
|
+
providerId: string,
|
|
285
|
+
activeSettings: Settings = settings ??
|
|
286
|
+
(() => {
|
|
287
|
+
throw new Error("Capability settings unavailable");
|
|
288
|
+
})(),
|
|
289
|
+
): void {
|
|
290
|
+
const providers = new Set(activeSettings.get("disabledProviders"));
|
|
291
|
+
providers.delete(providerId);
|
|
292
|
+
persistDisabledProviders(activeSettings, providers);
|
|
284
293
|
}
|
|
285
294
|
|
|
286
|
-
/**
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
295
|
+
/** Check whether a provider is enabled by the supplied session settings. */
|
|
296
|
+
export function isProviderEnabled(
|
|
297
|
+
providerId: string,
|
|
298
|
+
activeSettings: Settings | undefined = settings ?? undefined,
|
|
299
|
+
): boolean {
|
|
300
|
+
return !new Set(activeSettings?.get("disabledProviders") ?? disabledProviders).has(providerId);
|
|
291
301
|
}
|
|
292
302
|
|
|
293
|
-
/**
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
export function getDisabledProviders(): string[] {
|
|
297
|
-
return Array.from(disabledProviders);
|
|
303
|
+
/** Get disabled providers from the supplied session settings. */
|
|
304
|
+
export function getDisabledProviders(activeSettings: Settings | undefined = settings ?? undefined): string[] {
|
|
305
|
+
return [...(activeSettings?.get("disabledProviders") ?? disabledProviders)];
|
|
298
306
|
}
|
|
299
307
|
|
|
300
|
-
/**
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
persistDisabledProviders();
|
|
308
|
+
/** Replace disabled providers for the supplied session settings. */
|
|
309
|
+
export function setDisabledProviders(
|
|
310
|
+
providerIds: string[],
|
|
311
|
+
activeSettings: Settings = settings ??
|
|
312
|
+
(() => {
|
|
313
|
+
throw new Error("Capability settings unavailable");
|
|
314
|
+
})(),
|
|
315
|
+
): void {
|
|
316
|
+
persistDisabledProviders(activeSettings, new Set(providerIds));
|
|
309
317
|
}
|
|
310
318
|
|
|
311
319
|
// =============================================================================
|
package/src/capability/types.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and get back a unified array of MCP servers.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { Settings } from "../config/settings";
|
|
9
10
|
/**
|
|
10
11
|
* Context passed to every provider loader.
|
|
11
12
|
*/
|
|
@@ -72,6 +73,8 @@ export interface LoadOptions {
|
|
|
72
73
|
includeDisabled?: boolean;
|
|
73
74
|
/** Explicit disabled extension IDs to apply instead of settings. */
|
|
74
75
|
disabledExtensions?: string[];
|
|
76
|
+
/** Session settings whose provider policy applies to this load. */
|
|
77
|
+
settings?: Settings;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
package/src/cli/args.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI argument parsing
|
|
2
|
+
* CLI argument parsing
|
|
3
3
|
*/
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { type Effort, THINKING_EFFORTS } from "@gajae-code/ai";
|
|
6
|
-
import {
|
|
6
|
+
import { logger } from "@gajae-code/utils";
|
|
7
7
|
import { CliParseError } from "@gajae-code/utils/cli";
|
|
8
|
-
import chalk from "chalk";
|
|
9
8
|
import { parseEffort } from "../thinking";
|
|
10
9
|
import { BUILTIN_TOOLS } from "../tools";
|
|
11
10
|
|
|
@@ -253,92 +252,3 @@ export function parseArgs(args: string[]): Args {
|
|
|
253
252
|
|
|
254
253
|
return result;
|
|
255
254
|
}
|
|
256
|
-
|
|
257
|
-
export function getExtraHelpText(): string {
|
|
258
|
-
return `${chalk.bold("Environment Variables:")}
|
|
259
|
-
${chalk.dim("# Core Providers")}
|
|
260
|
-
ANTHROPIC_API_KEY - Anthropic Claude models
|
|
261
|
-
ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth (takes precedence over API key)
|
|
262
|
-
CLAUDE_CODE_USE_FOUNDRY - Enable Anthropic Foundry mode (uses Foundry endpoint + mTLS)
|
|
263
|
-
FOUNDRY_BASE_URL - Anthropic Foundry base URL (e.g., https://<foundry-host>)
|
|
264
|
-
ANTHROPIC_FOUNDRY_API_KEY - Anthropic token used as Authorization: Bearer <token> in Foundry mode
|
|
265
|
-
ANTHROPIC_CUSTOM_HEADERS - Extra Foundry headers (e.g., "user-id: USERNAME")
|
|
266
|
-
CLAUDE_CODE_CLIENT_CERT - Client certificate (PEM path or inline PEM) for mTLS
|
|
267
|
-
CLAUDE_CODE_CLIENT_KEY - Client private key (PEM path or inline PEM) for mTLS
|
|
268
|
-
NODE_EXTRA_CA_CERTS - CA bundle path (or inline PEM) for server certificate validation
|
|
269
|
-
OPENAI_API_KEY - OpenAI GPT models
|
|
270
|
-
GEMINI_API_KEY - Google Gemini models
|
|
271
|
-
GITHUB_TOKEN - GitHub Copilot (or GH_TOKEN, COPILOT_GITHUB_TOKEN)
|
|
272
|
-
|
|
273
|
-
${chalk.dim("# Additional LLM Providers")}
|
|
274
|
-
AZURE_OPENAI_API_KEY - Azure OpenAI models
|
|
275
|
-
GROQ_API_KEY - Groq models
|
|
276
|
-
CEREBRAS_API_KEY - Cerebras models
|
|
277
|
-
XAI_API_KEY - xAI Grok models
|
|
278
|
-
OPENROUTER_API_KEY - OpenRouter aggregated models
|
|
279
|
-
KILO_API_KEY - Kilo Gateway models
|
|
280
|
-
MISTRAL_API_KEY - Mistral models
|
|
281
|
-
ZAI_API_KEY - z.ai models (ZhipuAI/GLM)
|
|
282
|
-
MINIMAX_API_KEY - MiniMax models
|
|
283
|
-
OPENCODE_API_KEY - OpenCode Zen/OpenCode Go models
|
|
284
|
-
CURSOR_ACCESS_TOKEN - Cursor AI models
|
|
285
|
-
AI_GATEWAY_API_KEY - Vercel AI Gateway
|
|
286
|
-
|
|
287
|
-
${chalk.dim("# Cloud Providers")}
|
|
288
|
-
AWS_PROFILE - AWS Bedrock (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)
|
|
289
|
-
GOOGLE_CLOUD_PROJECT - Google Vertex AI (requires GOOGLE_CLOUD_LOCATION)
|
|
290
|
-
GOOGLE_APPLICATION_CREDENTIALS - Service account for Vertex AI
|
|
291
|
-
|
|
292
|
-
${chalk.dim("# Search & Tools")}
|
|
293
|
-
EXA_API_KEY - Exa web search
|
|
294
|
-
BRAVE_API_KEY - Brave web search
|
|
295
|
-
PERPLEXITY_API_KEY - Perplexity web search (API)
|
|
296
|
-
PERPLEXITY_COOKIES - Perplexity web search (session cookie)
|
|
297
|
-
TAVILY_API_KEY - Tavily web search
|
|
298
|
-
ANTHROPIC_SEARCH_API_KEY - Anthropic search provider
|
|
299
|
-
|
|
300
|
-
${chalk.dim("# Configuration")}
|
|
301
|
-
GJC_CODING_AGENT_DIR - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
302
|
-
GJC_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
|
303
|
-
GJC_SMOL_MODEL - Override smol/fast model (see --smol)
|
|
304
|
-
GJC_SLOW_MODEL - Override slow/reasoning model (see --slow)
|
|
305
|
-
GJC_PLAN_MODEL - Override planning model (see --plan)
|
|
306
|
-
GJC_NO_PTY - Disable PTY-based interactive bash execution
|
|
307
|
-
--tmux - Launch interactive startup inside a fresh tmux session
|
|
308
|
-
gjc session - List, inspect, create, remove, or attach tagged GJC-managed tmux sessions
|
|
309
|
-
GJC_LAUNCH_POLICY - Launch policy for --tmux startup: tmux or direct
|
|
310
|
-
GJC_TMUX_SESSION - Explicit tmux session name override for --tmux startup
|
|
311
|
-
GJC_TMUX_PROFILE - Apply GJC tmux scroll/mouse/clipboard profile to --tmux sessions (set 0/off to skip)
|
|
312
|
-
GJC_MOUSE - Mouse-wheel scroll in --tmux sessions (set 0/off to let the host terminal scroll)
|
|
313
|
-
|
|
314
|
-
For complete environment variable reference, see:
|
|
315
|
-
${chalk.dim("docs/environment-variables.md")}
|
|
316
|
-
${chalk.bold("Available Tools (default-enabled unless noted):")}
|
|
317
|
-
read - Read file contents
|
|
318
|
-
bash - Execute bash commands
|
|
319
|
-
edit - Edit files with find/replace
|
|
320
|
-
write - Write files (creates/overwrites)
|
|
321
|
-
grep - Search file contents
|
|
322
|
-
find - Find files by glob pattern
|
|
323
|
-
lsp - Language server protocol (code intelligence)
|
|
324
|
-
python - Execute Python code (requires: ${APP_NAME} setup python)
|
|
325
|
-
notebook - Edit Jupyter notebooks
|
|
326
|
-
browser - Browser automation (Puppeteer)
|
|
327
|
-
task - Launch sub-agents for parallel tasks
|
|
328
|
-
todo_write - Manage todo/task lists
|
|
329
|
-
web_search - Search the web
|
|
330
|
-
ask - Ask user questions (interactive mode only)
|
|
331
|
-
|
|
332
|
-
${chalk.bold("Useful Commands:")}
|
|
333
|
-
${APP_NAME} --list-models - List configured provider models
|
|
334
|
-
${APP_NAME} --help - Show this help`;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export function printHelp(): void {
|
|
338
|
-
process.stdout.write(
|
|
339
|
-
`${chalk.bold(APP_NAME)} - red-claw AI coding assistant\n\n` +
|
|
340
|
-
`Run ${APP_NAME} --help for full command and option details.\n` +
|
|
341
|
-
`Run ${APP_NAME} <command> --help for command-specific help.\n\n` +
|
|
342
|
-
`${getExtraHelpText()}\n`,
|
|
343
|
-
);
|
|
344
|
-
}
|
package/src/cli/notify-cli.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { createInterface } from "node:readline/promises";
|
|
|
7
7
|
import { APP_NAME } from "@gajae-code/utils/dirs";
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
import { Settings, type SettingsAtomicPatch } from "../config/settings";
|
|
10
|
-
import { isProcessIncarnation, processIncarnation } from "../sdk/broker/process-incarnation";
|
|
11
10
|
import { type EnsureChatDaemonResult, ensureDiscordDaemon, ensureSlackDaemon } from "../sdk/bus/chat-daemon-control";
|
|
12
11
|
import { getNotificationConfig, maskToken, tokenFingerprint } from "../sdk/bus/config";
|
|
13
12
|
import {
|
|
@@ -33,7 +32,7 @@ import {
|
|
|
33
32
|
import {
|
|
34
33
|
type EnsureTelegramDaemonDetailedResult,
|
|
35
34
|
ensureTelegramDaemonRunningDetailed,
|
|
36
|
-
|
|
35
|
+
resolveTelegramSetupPreflight,
|
|
37
36
|
} from "../sdk/bus/telegram-daemon";
|
|
38
37
|
import { runDaemonInternal } from "../sdk/bus/telegram-daemon-cli";
|
|
39
38
|
import {
|
|
@@ -458,42 +457,10 @@ function proposedIdentityFromSetupPreflight(
|
|
|
458
457
|
|
|
459
458
|
async function resolveSetupPreflight(settings: Settings, deps: NotifyCommandDeps): Promise<TelegramSetupPreflight> {
|
|
460
459
|
if (deps.setupPreflight) return deps.setupPreflight;
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const validPid = Number.isSafeInteger(state.pid) && state.pid > 0;
|
|
466
|
-
if (!validPid || !(deps.setupPidAlive ?? daemonPidAlive)(state.pid)) return { storedChatId: cfg.chatId };
|
|
467
|
-
const persistedIncarnation = state.incarnation;
|
|
468
|
-
const currentIncarnation = (deps.setupPidIncarnation ?? processIncarnation)(state.pid);
|
|
469
|
-
if (
|
|
470
|
-
!isProcessIncarnation(persistedIncarnation) ||
|
|
471
|
-
!isProcessIncarnation(currentIncarnation) ||
|
|
472
|
-
persistedIncarnation !== currentIncarnation
|
|
473
|
-
)
|
|
474
|
-
return { storedChatId: cfg.chatId };
|
|
475
|
-
return {
|
|
476
|
-
storedChatId: cfg.chatId,
|
|
477
|
-
daemon: {
|
|
478
|
-
live: true,
|
|
479
|
-
tokenFingerprint: typeof state.tokenFingerprint === "string" ? state.tokenFingerprint : undefined,
|
|
480
|
-
chatId: typeof state.chatId === "string" ? state.chatId : undefined,
|
|
481
|
-
},
|
|
482
|
-
};
|
|
483
|
-
} catch {
|
|
484
|
-
// A state read failure is not proof of a live daemon; proceed normally. The
|
|
485
|
-
// daemon's own 409 handling remains the backstop against poller contention.
|
|
486
|
-
return { storedChatId: cfg.chatId };
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function daemonPidAlive(pid: number): boolean {
|
|
491
|
-
try {
|
|
492
|
-
process.kill(pid, 0);
|
|
493
|
-
return true;
|
|
494
|
-
} catch (error) {
|
|
495
|
-
return (error as NodeJS.ErrnoException).code === "EPERM";
|
|
496
|
-
}
|
|
460
|
+
return await resolveTelegramSetupPreflight(settings, {
|
|
461
|
+
pidAlive: deps.setupPidAlive,
|
|
462
|
+
pidIncarnation: deps.setupPidIncarnation,
|
|
463
|
+
});
|
|
497
464
|
}
|
|
498
465
|
|
|
499
466
|
type TokenPromptInput = NodeJS.ReadStream & {
|
package/src/cli/setup-cli.ts
CHANGED
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
} from "../hooks/codex-native-hooks-config";
|
|
19
19
|
import { theme } from "../modes/theme/theme";
|
|
20
20
|
import { formatCredentialAutoImportResult, runExternalCredentialAutoImport } from "../setup/credential-auto-import";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
formatDiscoverySummary,
|
|
23
|
+
getAutoImportOAuthCredentialSkips,
|
|
24
|
+
isAutoImportOAuthCredential,
|
|
25
|
+
} from "../setup/credential-import";
|
|
22
26
|
import {
|
|
23
27
|
formatHermesSetupResult,
|
|
24
28
|
type HermesSetupFlags,
|
|
@@ -596,8 +600,10 @@ export async function handleCredentialsSetup(
|
|
|
596
600
|
trigger: "setup-cli",
|
|
597
601
|
});
|
|
598
602
|
const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
599
|
-
const
|
|
600
|
-
const
|
|
603
|
+
const now = Date.now();
|
|
604
|
+
const candidates = result.importable.filter(credential => isAutoImportOAuthCredential(credential, now));
|
|
605
|
+
const autoImportSkips = getAutoImportOAuthCredentialSkips(result.importable, now);
|
|
606
|
+
const filteredResult = { ...result, importable: candidates, skipped: [...result.skipped, ...autoImportSkips] };
|
|
601
607
|
const redactedPlan = {
|
|
602
608
|
importable: candidates.map(c => ({
|
|
603
609
|
provider: c.provider,
|
|
@@ -607,7 +613,7 @@ export async function handleCredentialsSetup(
|
|
|
607
613
|
expiresAt: c.expiresAt,
|
|
608
614
|
redactedToken: c.redactedToken,
|
|
609
615
|
})),
|
|
610
|
-
skipped:
|
|
616
|
+
skipped: filteredResult.skipped,
|
|
611
617
|
environment: result.environment,
|
|
612
618
|
keychainChecked: flags.keychain === true,
|
|
613
619
|
};
|