@songsid/agend 2.2.0 → 2.3.0-beta.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/dist/agent-cli.js +248 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +2 -0
- package/dist/agent-endpoint.js +25 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.d.ts +30 -0
- package/dist/agent-file-read.js +129 -0
- package/dist/agent-file-read.js.map +1 -0
- package/dist/agent-whats-new.js +13 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/atomic-write.js +9 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.js +17 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.js +3 -3
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/launch-effort.js +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/muse.js +10 -2
- package/dist/backend/muse.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +2 -0
- package/dist/channel/adapters/discord.js +17 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +8 -1
- package/dist/channel/adapters/telegram.js +74 -4
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +34 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/types.d.ts +15 -0
- package/dist/config-validator.js +17 -1
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.js +244 -20
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-manager.d.ts +89 -0
- package/dist/fleet-manager.js +401 -25
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +258 -0
- package/dist/instance-avatar.js +3 -0
- package/dist/instance-avatar.js.map +1 -1
- package/dist/instance-config-impact.js +3 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.js +9 -4
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/needs-you-hub.d.ts +4 -0
- package/dist/needs-you-hub.js +31 -6
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +1 -13
- package/dist/needs-you.js +3 -37
- package/dist/needs-you.js.map +1 -1
- package/dist/outbound-handlers.d.ts +5 -0
- package/dist/outbound-handlers.js +30 -9
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +64 -0
- package/dist/outbound-schemas.js +50 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +14 -0
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/repo-worktree-guard.d.ts +36 -0
- package/dist/repo-worktree-guard.js +143 -0
- package/dist/repo-worktree-guard.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +58 -1
- package/dist/scheduler/scheduler.js +176 -10
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/settings-api.js +74 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +8 -0
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +16 -2
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +5 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/tool-permissions.js +50 -0
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.d.ts +10 -6
- package/dist/topic-commands.js +21 -17
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.d.ts +128 -0
- package/dist/topic-link.js +269 -0
- package/dist/topic-link.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/ui/app-effects.js +187 -0
- package/dist/ui/chat-effect-posters.js +42 -0
- package/dist/ui/chat-effects.js +72 -0
- package/dist/ui/chat-live-replies.js +58 -0
- package/dist/ui/chat-render.js +4 -4
- package/dist/ui/chat-store.js +9 -3
- package/dist/ui/chat-strings.js +15 -0
- package/dist/ui/chat-thread.js +47 -21
- package/dist/ui/chat-tour.js +1 -1
- package/dist/ui/effect-trial-controller.js +119 -0
- package/dist/ui/effect-trial-offer.js +31 -0
- package/dist/ui/effect-trial-panel.js +37 -0
- package/dist/ui/image-lightbox.js +1 -1
- package/dist/ui/panel-chat.js +85 -17
- package/dist/ui/panel-details.js +18 -5
- package/dist/ui/panel-fleet.js +3 -3
- package/dist/ui/panel-log.js +6 -6
- package/dist/ui/panel-needs.js +3 -3
- package/dist/ui/panel-settings.js +8 -5
- package/dist/ui/preview-panel.js +25 -9
- package/dist/ui/settings-appearance.js +325 -0
- package/dist/ui/settings-effects.js +201 -0
- package/dist/ui/settings-mods.js +257 -0
- package/dist/ui/settings-owner-effects.js +80 -0
- package/dist/ui/settings-strings.js +245 -0
- package/dist/ui/shared/agend-auth.js +27 -3
- package/dist/ui/shared/agent-widget.js +248 -0
- package/dist/ui/shared/app-i18n.js +2 -0
- package/dist/ui/shared/app-prefs.js +30 -10
- package/dist/ui/shared/app-route.js +23 -1
- package/dist/ui/shared/app-session.js +1 -1
- package/dist/ui/shared/app-shell.js +29 -16
- package/dist/ui/shared/app-store.js +2 -0
- package/dist/ui/shared/app-stream.js +12 -7
- package/dist/ui/shared/app-themes.js +188 -0
- package/dist/ui/shared/app.css +214 -1
- package/dist/ui/shared/app.js +6 -0
- package/dist/ui/shared/card-strings.js +28 -0
- package/dist/ui/shared/effect-app-runtime.js +248 -0
- package/dist/ui/shared/effect-baseline.js +64 -0
- package/dist/ui/shared/effect-chat-runtime.js +154 -0
- package/dist/ui/shared/effect-cursor.js +125 -0
- package/dist/ui/shared/effect-frame.js +127 -0
- package/dist/ui/shared/effect-geometry.js +122 -0
- package/dist/ui/shared/effect-host-style.js +10 -0
- package/dist/ui/shared/effect-owner-regions.js +74 -0
- package/dist/ui/shared/effect-owner-source.js +115 -0
- package/dist/ui/shared/effect-policy.js +137 -0
- package/dist/ui/shared/effect-poster-reader.js +98 -0
- package/dist/ui/shared/effect-posters.js +117 -0
- package/dist/ui/shared/effect-profiler.js +162 -0
- package/dist/ui/shared/effect-profiles.js +65 -0
- package/dist/ui/shared/effect-registry.js +496 -0
- package/dist/ui/shared/effect-runtime-loader.js +234 -0
- package/dist/ui/shared/effect-safety.js +153 -0
- package/dist/ui/shared/effect-stock-snapshot.js +34 -0
- package/dist/ui/shared/effect-stock-trust.js +165 -0
- package/dist/ui/shared/effect-trial-source.js +103 -0
- package/dist/ui/shared/effect-trial-stage.js +147 -0
- package/dist/ui/shared/header-tools.js +1 -1
- package/dist/ui/shared/identity-card.js +202 -0
- package/dist/ui/shared/identity-color.js +261 -0
- package/dist/ui/shared/instance-nav.js +22 -14
- package/dist/ui/shared/owner-css.js +221 -0
- package/dist/ui/shared/owner-effect-prefs.js +117 -0
- package/dist/ui/shared/panel-view.js +81 -8
- package/dist/ui/shared/signin.js +2 -0
- package/dist/ui/shared/ui-dialog.js +1 -1
- package/dist/ui/shared/ui-icons.js +2 -0
- package/dist/ui/shared/ui-menu.js +1 -1
- package/dist/ui/shared/ui-toast.js +1 -1
- package/dist/ui/shared/view-strings.js +30 -0
- package/dist/ui/signin.html +1 -0
- package/dist/view-api.d.ts +29 -0
- package/dist/view-api.js +188 -8
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +42 -0
- package/dist/web-api.js +896 -36
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-limits.d.ts +82 -0
- package/dist/web-appearance-limits.js +83 -0
- package/dist/web-appearance-limits.js.map +1 -0
- package/dist/web-appearance-policy.d.ts +66 -0
- package/dist/web-appearance-policy.js +94 -0
- package/dist/web-appearance-policy.js.map +1 -0
- package/dist/web-appearance-tools.d.ts +50 -0
- package/dist/web-appearance-tools.js +105 -0
- package/dist/web-appearance-tools.js.map +1 -0
- package/dist/web-appearance-view.d.ts +99 -0
- package/dist/web-appearance-view.js +163 -0
- package/dist/web-appearance-view.js.map +1 -0
- package/dist/web-appearance.d.ts +79 -0
- package/dist/web-appearance.js +298 -0
- package/dist/web-appearance.js.map +1 -0
- package/dist/web-asset-parts.d.ts +98 -0
- package/dist/web-asset-parts.js +133 -0
- package/dist/web-asset-parts.js.map +1 -0
- package/dist/web-auth.js +17 -1
- package/dist/web-auth.js.map +1 -1
- package/dist/web-card.d.ts +96 -0
- package/dist/web-card.js +232 -0
- package/dist/web-card.js.map +1 -0
- package/dist/web-chat-history.d.ts +13 -0
- package/dist/web-chat-history.js +23 -2
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-effect-bundle.d.ts +28 -0
- package/dist/web-effect-bundle.js +126 -0
- package/dist/web-effect-bundle.js.map +1 -0
- package/dist/web-effect-canonical.d.ts +8 -0
- package/dist/web-effect-canonical.js +27 -0
- package/dist/web-effect-canonical.js.map +1 -0
- package/dist/web-effect-library.d.ts +114 -0
- package/dist/web-effect-library.js +530 -0
- package/dist/web-effect-library.js.map +1 -0
- package/dist/web-effect-poster.d.ts +8 -0
- package/dist/web-effect-poster.js +52 -0
- package/dist/web-effect-poster.js.map +1 -0
- package/dist/web-effect-profiles.d.ts +118 -0
- package/dist/web-effect-profiles.js +180 -0
- package/dist/web-effect-profiles.js.map +1 -0
- package/dist/web-effect-service.d.ts +86 -0
- package/dist/web-effect-service.js +312 -0
- package/dist/web-effect-service.js.map +1 -0
- package/dist/web-effect-tools.d.ts +47 -0
- package/dist/web-effect-tools.js +126 -0
- package/dist/web-effect-tools.js.map +1 -0
- package/dist/web-effect-trials.d.ts +86 -0
- package/dist/web-effect-trials.js +204 -0
- package/dist/web-effect-trials.js.map +1 -0
- package/dist/web-effect-upload.d.ts +29 -0
- package/dist/web-effect-upload.js +190 -0
- package/dist/web-effect-upload.js.map +1 -0
- package/dist/web-effect-worker.d.ts +8 -0
- package/dist/web-effect-worker.js +170 -0
- package/dist/web-effect-worker.js.map +1 -0
- package/dist/web-effect.d.ts +89 -0
- package/dist/web-effect.js +132 -0
- package/dist/web-effect.js.map +1 -0
- package/dist/web-identity-color.d.ts +87 -0
- package/dist/web-identity-color.js +209 -0
- package/dist/web-identity-color.js.map +1 -0
- package/dist/web-identity-palette.d.ts +113 -0
- package/dist/web-identity-palette.js +84 -0
- package/dist/web-identity-palette.js.map +1 -0
- package/dist/web-image-meta.d.ts +25 -0
- package/dist/web-image-meta.js +200 -0
- package/dist/web-image-meta.js.map +1 -0
- package/dist/web-mod-agent.d.ts +50 -0
- package/dist/web-mod-agent.js +203 -0
- package/dist/web-mod-agent.js.map +1 -0
- package/dist/web-mod-bundle.d.ts +144 -0
- package/dist/web-mod-bundle.js +464 -0
- package/dist/web-mod-bundle.js.map +1 -0
- package/dist/web-mod-export.d.ts +59 -0
- package/dist/web-mod-export.js +79 -0
- package/dist/web-mod-export.js.map +1 -0
- package/dist/web-mod-store.d.ts +283 -0
- package/dist/web-mod-store.js +624 -0
- package/dist/web-mod-store.js.map +1 -0
- package/dist/web-org.d.ts +3 -3
- package/dist/web-org.js +11 -17
- package/dist/web-org.js.map +1 -1
- package/dist/web-owner-css-store.d.ts +180 -0
- package/dist/web-owner-css-store.js +384 -0
- package/dist/web-owner-css-store.js.map +1 -0
- package/dist/web-owner-css.d.ts +58 -0
- package/dist/web-owner-css.js +552 -0
- package/dist/web-owner-css.js.map +1 -0
- package/dist/web-prefs.d.ts +48 -0
- package/dist/web-prefs.js +209 -33
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +9 -1
- package/dist/web-preview.js +24 -7
- package/dist/web-preview.js.map +1 -1
- package/dist/web-settings-patch.d.ts +18 -0
- package/dist/web-settings-patch.js +51 -0
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-shell-routes.d.ts +1 -1
- package/dist/web-shell-routes.js +1 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-theme-store.d.ts +218 -0
- package/dist/web-theme-store.js +516 -0
- package/dist/web-theme-store.js.map +1 -0
- package/dist/web-theme.d.ts +121 -0
- package/dist/web-theme.js +407 -0
- package/dist/web-theme.js.map +1 -0
- package/dist/web-widget.d.ts +72 -0
- package/dist/web-widget.js +245 -0
- package/dist/web-widget.js.map +1 -0
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AGENT_WHATS_NEW, agendVersion, planWhatsNew, readWhatsNewRecord, recordWhatsNew, whatsNewNotice } from "./agent-whats-new.js";
|
|
2
|
-
import { join, dirname,
|
|
2
|
+
import { join, dirname, resolve } from "node:path";
|
|
3
|
+
import { checkoutTarget, readCheckouts, releaseCandidate, reposRoot, verifyWorktree, writeCheckouts } from "./repo-worktree-guard.js";
|
|
3
4
|
import { mkdirSync, writeFileSync, readFileSync, readdirSync, existsSync, unlinkSync, rmSync, appendFileSync, statSync, renameSync } from "node:fs";
|
|
4
5
|
import { COMPACT_WATCH_TIMEOUT_MS, launchIdentity } from "./compact-watch.js";
|
|
5
6
|
import { KIRO_COMPACT_PANE_LINES, KiroCompactPaneFollower } from "./kiro-compact-pane.js";
|
|
@@ -19,6 +20,9 @@ import { TranscriptTurnLedger } from "./transcript-turns.js";
|
|
|
19
20
|
import { credentialProfileStoreHome, resolveCredentialProfile } from "./backend/credential-profile.js";
|
|
20
21
|
import { resolveToolSet } from "./tool-permissions.js";
|
|
21
22
|
import { getAgendHome } from "./paths.js";
|
|
23
|
+
import { readAgentEffect, sendEffectInParts } from "./web-effect-upload.js";
|
|
24
|
+
import { readAgentFile } from "./agent-file-read.js";
|
|
25
|
+
import { ASSET_UPLOAD_MAX_BYTES, MOD_FILE, MOD_MAX_PARTS, MOD_UPLOAD_MAX_BYTES, receiveFiles, receivePreview, sendAssetInParts, writeModFile, writePreview } from "./web-asset-parts.js";
|
|
22
26
|
import { LOGIN_FLOWS } from "./login-flows.js";
|
|
23
27
|
import { ProgressAccumulator, summarizeProgress } from "./tool-progress.js";
|
|
24
28
|
import { assembleSystemPrompt, resolveWorkflowText } from "./prompt-file-ref.js";
|
|
@@ -55,6 +59,26 @@ import { unrecognisedPromptShape } from "./unrecognised-prompt.js";
|
|
|
55
59
|
const __filename = fileURLToPath(import.meta.url);
|
|
56
60
|
const __dirname = dirname(__filename);
|
|
57
61
|
// Tool routing sets — module-level to avoid re-creation on every handleToolCall
|
|
62
|
+
/** #1629: the caller's own web theme tools, each its own typed IPC message (one tool per type, for the permission check). */
|
|
63
|
+
const WEB_THEME_IPC = Object.freeze({
|
|
64
|
+
get_web_theme: "fleet_get_web_theme", set_web_theme: "fleet_set_web_theme",
|
|
65
|
+
set_web_theme_asset: "fleet_set_web_theme_asset", reset_web_theme: "fleet_reset_web_theme",
|
|
66
|
+
// r4 §1: how it appears — read-only; a preview's files are written here, on the agent's side.
|
|
67
|
+
get_web_appearance: "fleet_get_web_appearance", preview_web_appearance: "fleet_preview_web_appearance",
|
|
68
|
+
// r4-4: its own declarative widgets.
|
|
69
|
+
set_web_widget: "fleet_set_web_widget", remove_web_widget: "fleet_remove_web_widget",
|
|
70
|
+
// r4-5b: mods — an export's file is written here, a proposal's file read here (on the agent's side).
|
|
71
|
+
export_web_mod: "fleet_export_web_mod", propose_web_mod: "fleet_propose_web_mod",
|
|
72
|
+
upload_web_effect: "fleet_upload_web_effect",
|
|
73
|
+
list_web_effects: "fleet_list_web_effects",
|
|
74
|
+
preview_web_effect: "fleet_preview_web_effect",
|
|
75
|
+
profile_web_effect: "fleet_profile_web_effect",
|
|
76
|
+
apply_web_effect: "fleet_apply_web_effect",
|
|
77
|
+
remove_web_effect: "fleet_remove_web_effect",
|
|
78
|
+
delete_web_effect: "fleet_delete_web_effect",
|
|
79
|
+
});
|
|
80
|
+
/** The largest picture any slot may take (a card slot's ceiling; the fleet checks the limit in force): read no more. */
|
|
81
|
+
const WEB_THEME_ASSET_MAX_BYTES = ASSET_UPLOAD_MAX_BYTES;
|
|
58
82
|
const CROSS_INSTANCE_TOOLS = new Set(["send_to_instance", "broadcast", "list_instances", "start_instance", "restart_instance", "create_instance", "delete_instance", "replace_instance", "request_information", "delegate_task", "report_result", "delivery_status", "describe_instance"]);
|
|
59
83
|
const SCHEDULE_TOOLS = new Set(["create_schedule", "list_schedules", "update_schedule", "delete_schedule"]);
|
|
60
84
|
const DECISION_TOOLS = new Set(["post_decision", "list_decisions", "update_decision"]);
|
|
@@ -1073,7 +1097,7 @@ export class BlockingProcessDetector {
|
|
|
1073
1097
|
/** Response types the fleet sends back for tool calls the daemon forwarded. */
|
|
1074
1098
|
const FLEET_RESPONSE_TYPES = new Set([
|
|
1075
1099
|
"fleet_schedule_response", "fleet_outbound_response", "fleet_decision_response", "fleet_task_response",
|
|
1076
|
-
"fleet_display_name_response", "fleet_description_response", "fleet_persona_emoji_response",
|
|
1100
|
+
"fleet_display_name_response", "fleet_description_response", "fleet_persona_emoji_response", "fleet_web_theme_response",
|
|
1077
1101
|
]);
|
|
1078
1102
|
export class Daemon extends EventEmitter {
|
|
1079
1103
|
name;
|
|
@@ -9945,6 +9969,169 @@ export class Daemon extends EventEmitter {
|
|
|
9945
9969
|
});
|
|
9946
9970
|
return;
|
|
9947
9971
|
}
|
|
9972
|
+
// #1629: the caller's own web theme. set_web_theme_asset's file is read HERE, on the agent's side (in its working
|
|
9973
|
+
// directory, no symlink, size-capped): the fleet receives bytes, never a workspace path.
|
|
9974
|
+
if (Object.hasOwn(WEB_THEME_IPC, tool)) {
|
|
9975
|
+
// Answered exactly once, whatever happens on the way (#1887 review: a throw here once left the call unanswered).
|
|
9976
|
+
let answered = false;
|
|
9977
|
+
const reply = (result, error) => { if (answered)
|
|
9978
|
+
return; answered = true; respond(result, error); };
|
|
9979
|
+
// One fleet request; resolves with its answer, or an error string (never rejects).
|
|
9980
|
+
const ask = (payload) => new Promise((resolve) => {
|
|
9981
|
+
const fleetReqId = `theme_${++this.fleetRequestSeq}_${requestId}`;
|
|
9982
|
+
const timeout = setTimeout(() => {
|
|
9983
|
+
this.pendingIpcRequests.delete(fleetReqId);
|
|
9984
|
+
resolve({ result: null, error: `${tool} timed out` });
|
|
9985
|
+
}, daemonBudgetMs(tool));
|
|
9986
|
+
this.pendingIpcRequests.set(fleetReqId, (respMsg) => {
|
|
9987
|
+
clearTimeout(timeout);
|
|
9988
|
+
resolve({ result: respMsg.result, error: respMsg.error });
|
|
9989
|
+
});
|
|
9990
|
+
this.ipcServer?.broadcast({ type: WEB_THEME_IPC[tool], payload, meta: { instance_name: this.name }, fleetRequestId: fleetReqId });
|
|
9991
|
+
});
|
|
9992
|
+
void (async () => {
|
|
9993
|
+
if (tool === "preview_web_appearance") {
|
|
9994
|
+
// The fleet builds the SVGs (whole, or in parts); they are written here, in the working directory.
|
|
9995
|
+
const first = await ask({ ...(args.modes !== undefined ? { modes: args.modes } : {}) });
|
|
9996
|
+
if (first.error) {
|
|
9997
|
+
reply(null, first.error);
|
|
9998
|
+
return;
|
|
9999
|
+
}
|
|
10000
|
+
let failed;
|
|
10001
|
+
const got = await receivePreview((first.result && typeof first.result === "object" ? first.result : {}), async (payload) => {
|
|
10002
|
+
const r = await ask(payload);
|
|
10003
|
+
if (r.error) {
|
|
10004
|
+
failed = r.error;
|
|
10005
|
+
return { error: r.error };
|
|
10006
|
+
}
|
|
10007
|
+
return (r.result && typeof r.result === "object" ? r.result : {});
|
|
10008
|
+
});
|
|
10009
|
+
if (failed) {
|
|
10010
|
+
reply(null, failed);
|
|
10011
|
+
return;
|
|
10012
|
+
}
|
|
10013
|
+
if ("error" in got) {
|
|
10014
|
+
reply(got, undefined);
|
|
10015
|
+
return;
|
|
10016
|
+
}
|
|
10017
|
+
const written = await writePreview(got.files, { workspace: this.config.working_directory, stateDir: getAgendHome() });
|
|
10018
|
+
if ("error" in written) {
|
|
10019
|
+
reply(null, `preview_web_appearance: ${written.error}`);
|
|
10020
|
+
return;
|
|
10021
|
+
}
|
|
10022
|
+
reply(written, undefined);
|
|
10023
|
+
return;
|
|
10024
|
+
}
|
|
10025
|
+
if (tool === "export_web_mod") {
|
|
10026
|
+
// The fleet builds the file (whole, or in parts); it is written here, in the working directory.
|
|
10027
|
+
const first = await ask(args);
|
|
10028
|
+
if (first.error) {
|
|
10029
|
+
reply(null, first.error);
|
|
10030
|
+
return;
|
|
10031
|
+
}
|
|
10032
|
+
let failed;
|
|
10033
|
+
const firstResult = (first.result && typeof first.result === "object" ? first.result : {});
|
|
10034
|
+
const got = await receiveFiles(firstResult, async (payload) => {
|
|
10035
|
+
const r = await ask(payload);
|
|
10036
|
+
if (r.error) {
|
|
10037
|
+
failed = r.error;
|
|
10038
|
+
return { error: r.error };
|
|
10039
|
+
}
|
|
10040
|
+
return (r.result && typeof r.result === "object" ? r.result : {});
|
|
10041
|
+
}, { name: MOD_FILE, idKey: "transfer", what: "export", maxParts: MOD_MAX_PARTS });
|
|
10042
|
+
if (failed) {
|
|
10043
|
+
reply(null, failed);
|
|
10044
|
+
return;
|
|
10045
|
+
}
|
|
10046
|
+
if ("error" in got) {
|
|
10047
|
+
reply(got, undefined);
|
|
10048
|
+
return;
|
|
10049
|
+
}
|
|
10050
|
+
const written = await writeModFile(got.files, { workspace: this.config.working_directory, stateDir: getAgendHome() });
|
|
10051
|
+
if ("error" in written) {
|
|
10052
|
+
reply(null, `export_web_mod: ${written.error}`);
|
|
10053
|
+
return;
|
|
10054
|
+
}
|
|
10055
|
+
reply({ ...written, ...(firstResult.effects_omitted ? { effects_omitted: firstResult.effects_omitted } : {}) }, undefined);
|
|
10056
|
+
return;
|
|
10057
|
+
}
|
|
10058
|
+
if (tool === "propose_web_mod") {
|
|
10059
|
+
const read = await readAgentFile(args.file, { workspace: this.config.working_directory, stateDir: getAgendHome(), maxBytes: MOD_UPLOAD_MAX_BYTES });
|
|
10060
|
+
const named = typeof args.file === "string" ? args.file.slice(0, 200) : "the file argument";
|
|
10061
|
+
if (!read.ok) {
|
|
10062
|
+
reply(null, `propose_web_mod: ${named} — ${read.reason}`);
|
|
10063
|
+
return;
|
|
10064
|
+
}
|
|
10065
|
+
let failed;
|
|
10066
|
+
const answer = await sendAssetInParts("mod", read.bytes, async (payload) => {
|
|
10067
|
+
const r = await ask(payload);
|
|
10068
|
+
if (r.error) {
|
|
10069
|
+
failed = r.error;
|
|
10070
|
+
return { error: r.error };
|
|
10071
|
+
}
|
|
10072
|
+
return (r.result && typeof r.result === "object" ? r.result : {});
|
|
10073
|
+
});
|
|
10074
|
+
reply(failed ? null : answer, failed);
|
|
10075
|
+
return;
|
|
10076
|
+
}
|
|
10077
|
+
if (tool === "upload_web_effect") {
|
|
10078
|
+
const owner = { fence: this.launchFenceEpoch, spawn: this.spawnGeneration, boot: this.bootId, ipc: this.ipcServer };
|
|
10079
|
+
const current = () => !!owner.ipc && owner.ipc === this.ipcServer && owner.fence === this.launchFenceEpoch && owner.spawn === this.spawnGeneration && owner.boot === this.bootId && !this.deliveryWritesStopping && !this.startupAborted;
|
|
10080
|
+
if (!current()) {
|
|
10081
|
+
reply(null, "upload_web_effect: launch no longer current");
|
|
10082
|
+
return;
|
|
10083
|
+
}
|
|
10084
|
+
const read = await readAgentEffect(args.dir, { workspace: this.config.working_directory, stateDir: getAgendHome() });
|
|
10085
|
+
if (!current()) {
|
|
10086
|
+
reply(null, "upload_web_effect: launch no longer current");
|
|
10087
|
+
return;
|
|
10088
|
+
}
|
|
10089
|
+
if (!read.ok) {
|
|
10090
|
+
reply(null, `upload_web_effect: ${read.reason}`);
|
|
10091
|
+
return;
|
|
10092
|
+
}
|
|
10093
|
+
let failed;
|
|
10094
|
+
const answer = await sendEffectInParts(read.files, async (payload) => {
|
|
10095
|
+
if (!current()) {
|
|
10096
|
+
failed = "upload_web_effect: launch no longer current";
|
|
10097
|
+
return { error: failed };
|
|
10098
|
+
}
|
|
10099
|
+
const r = await ask(payload);
|
|
10100
|
+
if (r.error) {
|
|
10101
|
+
failed = r.error;
|
|
10102
|
+
return { error: r.error };
|
|
10103
|
+
}
|
|
10104
|
+
return (r.result && typeof r.result === "object" ? r.result : {});
|
|
10105
|
+
});
|
|
10106
|
+
reply(failed ? null : answer, failed);
|
|
10107
|
+
return;
|
|
10108
|
+
}
|
|
10109
|
+
if (tool !== "set_web_theme_asset") {
|
|
10110
|
+
const r = await ask(args);
|
|
10111
|
+
reply(r.result, r.error);
|
|
10112
|
+
return;
|
|
10113
|
+
}
|
|
10114
|
+
const read = await readAgentFile(args.file, { workspace: this.config.working_directory, stateDir: getAgendHome(), maxBytes: WEB_THEME_ASSET_MAX_BYTES });
|
|
10115
|
+
// The path as the agent gave it — only a string is shown (an object from raw JSON args is never coerced).
|
|
10116
|
+
const named = typeof args.file === "string" ? args.file.slice(0, 200) : "the file argument";
|
|
10117
|
+
if (!read.ok) {
|
|
10118
|
+
reply(null, `set_web_theme_asset: ${named} — ${read.reason}`);
|
|
10119
|
+
return;
|
|
10120
|
+
}
|
|
10121
|
+
// A picture larger than one IPC message goes up in parts (r4 §1: a card portrait may be megabytes).
|
|
10122
|
+
let failed;
|
|
10123
|
+
const answer = await sendAssetInParts(args.slot, read.bytes, async (payload) => {
|
|
10124
|
+
const r = await ask(payload);
|
|
10125
|
+
if (r.error) {
|
|
10126
|
+
failed = r.error;
|
|
10127
|
+
return { error: r.error };
|
|
10128
|
+
}
|
|
10129
|
+
return (r.result && typeof r.result === "object" ? r.result : {});
|
|
10130
|
+
});
|
|
10131
|
+
reply(failed ? null : answer, failed);
|
|
10132
|
+
})().catch((err) => reply(null, `${tool} failed: ${err instanceof Error ? err.message : "error"}`));
|
|
10133
|
+
return;
|
|
10134
|
+
}
|
|
9948
10135
|
if (tool === TASK_TOOL) {
|
|
9949
10136
|
const fleetReqId = `task_${++this.fleetRequestSeq}_${requestId}`;
|
|
9950
10137
|
const timeout = setTimeout(() => {
|
|
@@ -12055,16 +12242,29 @@ export class Daemon extends EventEmitter {
|
|
|
12055
12242
|
respond(null, `Not a git repository: ${source}`);
|
|
12056
12243
|
return;
|
|
12057
12244
|
}
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
const
|
|
12061
|
-
|
|
12245
|
+
mkdirSync(join(this.instanceDir, "repos"), { recursive: true });
|
|
12246
|
+
// Only a fresh direct child of a real repos/ directory (never through a symlinked repos/, never an existing path).
|
|
12247
|
+
const target = checkoutTarget(this.instanceDir, source, branch);
|
|
12248
|
+
if (!target.ok) {
|
|
12249
|
+
respond(null, `checkout_repo: ${target.reason}`);
|
|
12250
|
+
return;
|
|
12251
|
+
}
|
|
12252
|
+
const worktreePath = target.path;
|
|
12062
12253
|
try {
|
|
12063
|
-
// Resolve branch/ref to verify it exists.
|
|
12064
|
-
//
|
|
12065
|
-
|
|
12066
|
-
await execFileAsync("git", ["
|
|
12254
|
+
// Resolve branch/ref to verify it exists. `--end-of-options` keeps git from ever reading branch as an option
|
|
12255
|
+
// flag (defense in depth on top of the regex above). Not `--`: rev-parse then reads branch as a path, and
|
|
12256
|
+
// `--verify` fails for every ref ("Needed a single revision"), which broke checkout_repo entirely.
|
|
12257
|
+
await execFileAsync("git", ["rev-parse", "--verify", "--end-of-options", `${branch}^{commit}`], { cwd: source });
|
|
12258
|
+
await execFileAsync("git", ["worktree", "add", "--detach", worktreePath, "--end-of-options", branch], { cwd: source });
|
|
12067
12259
|
const { stdout: commitHash } = await execFileAsync("git", ["rev-parse", "--short", "HEAD"], { cwd: worktreePath });
|
|
12260
|
+
// Recorded so release_repo can tell this instance's checkout of this repository from anything else.
|
|
12261
|
+
try {
|
|
12262
|
+
const { stdout: common } = await execFileAsync("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], { cwd: worktreePath });
|
|
12263
|
+
const root = reposRoot(this.instanceDir);
|
|
12264
|
+
if (root.ok)
|
|
12265
|
+
writeCheckouts(root.path, { ...readCheckouts(root.path), [worktreePath]: common.trim() });
|
|
12266
|
+
}
|
|
12267
|
+
catch { /* unrecorded: release still requires a listed linked worktree */ }
|
|
12068
12268
|
respond({ path: worktreePath, branch, source, commit: commitHash.trim() });
|
|
12069
12269
|
}
|
|
12070
12270
|
catch (err) {
|
|
@@ -12072,26 +12272,50 @@ export class Daemon extends EventEmitter {
|
|
|
12072
12272
|
}
|
|
12073
12273
|
}
|
|
12074
12274
|
async handleReleaseRepo(args, respond) {
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
if (!
|
|
12079
|
-
respond(null, `Cannot release
|
|
12275
|
+
// Containment first (real paths, strictly inside this instance's repos/), then proof it is a git worktree.
|
|
12276
|
+
// Nothing that fails either check is ever removed.
|
|
12277
|
+
const candidate = releaseCandidate(this.instanceDir, args.path);
|
|
12278
|
+
if (!candidate.ok) {
|
|
12279
|
+
respond(null, `Cannot release: ${candidate.reason}`);
|
|
12080
12280
|
return;
|
|
12081
12281
|
}
|
|
12282
|
+
const root = reposRoot(this.instanceDir);
|
|
12283
|
+
if (!root.ok) {
|
|
12284
|
+
respond(null, `Cannot release: ${root.reason}`);
|
|
12285
|
+
return;
|
|
12286
|
+
}
|
|
12287
|
+
const { execFile: execFileCb } = await import("node:child_process");
|
|
12288
|
+
const { promisify } = await import("node:util");
|
|
12289
|
+
const execFileAsync = promisify(execFileCb);
|
|
12290
|
+
const git = async (gitArgs, cwd) => (await execFileAsync("git", gitArgs, { cwd })).stdout;
|
|
12291
|
+
const worktree = await verifyWorktree(root.path, candidate.path, git);
|
|
12292
|
+
if (!worktree.ok) {
|
|
12293
|
+
respond(null, `Cannot release: ${worktree.reason}`);
|
|
12294
|
+
return;
|
|
12295
|
+
}
|
|
12296
|
+
const repoPath = candidate.path;
|
|
12082
12297
|
try {
|
|
12083
|
-
|
|
12084
|
-
const { promisify } = await import("node:util");
|
|
12085
|
-
const execFileAsync = promisify(execFileCb);
|
|
12086
|
-
await execFileAsync("git", ["worktree", "remove", "--force", repoPath]);
|
|
12298
|
+
await git(["--git-dir", worktree.commonDir, "worktree", "remove", "--force", repoPath], worktree.commonDir);
|
|
12087
12299
|
}
|
|
12088
12300
|
catch {
|
|
12089
|
-
// Fallback
|
|
12301
|
+
// Fallback for a verified worktree only: remove it, then let its repository forget it.
|
|
12090
12302
|
try {
|
|
12091
12303
|
rmSync(repoPath, { recursive: true, force: true });
|
|
12092
12304
|
}
|
|
12093
12305
|
catch { /* best effort */ }
|
|
12306
|
+
try {
|
|
12307
|
+
await git(["--git-dir", worktree.commonDir, "worktree", "prune"], worktree.commonDir);
|
|
12308
|
+
}
|
|
12309
|
+
catch { /* best effort */ }
|
|
12310
|
+
}
|
|
12311
|
+
try {
|
|
12312
|
+
const records = readCheckouts(root.path);
|
|
12313
|
+
if (repoPath in records) {
|
|
12314
|
+
delete records[repoPath];
|
|
12315
|
+
writeCheckouts(root.path, records);
|
|
12316
|
+
}
|
|
12094
12317
|
}
|
|
12318
|
+
catch { /* the worktree is gone; a stale record only refuses a later, different repo at this path */ }
|
|
12095
12319
|
respond({ released: true, path: repoPath });
|
|
12096
12320
|
}
|
|
12097
12321
|
buildSnapshotPrompt() {
|