@ouro.bot/cli 0.1.0-alpha.30 → 0.1.0-alpha.301
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 +188 -190
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
- package/changelog.json +1814 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +117 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +237 -0
- package/dist/arc/packets.js +203 -0
- package/dist/arc/presence.js +185 -0
- package/dist/heart/active-work.js +832 -0
- package/dist/heart/agent-entry.js +37 -2
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +230 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/store.js +103 -0
- package/dist/heart/attachments/types.js +138 -0
- package/dist/heart/auth/auth-flow.js +456 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +304 -0
- package/dist/heart/config.js +63 -30
- package/dist/heart/core.js +669 -195
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +149 -0
- package/dist/heart/daemon/agent-discovery.js +79 -3
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +574 -0
- package/dist/heart/daemon/cli-exec.js +1945 -0
- package/dist/heart/daemon/cli-parse.js +808 -0
- package/dist/heart/daemon/cli-render.js +503 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1171
- package/dist/heart/daemon/daemon-entry.js +245 -3
- package/dist/heart/daemon/daemon-health.js +136 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +706 -57
- package/dist/heart/daemon/health-monitor.js +38 -0
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/launchd.js +46 -9
- package/dist/heart/daemon/log-tailer.js +82 -12
- package/dist/heart/daemon/logs-prune.js +105 -0
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/os-cron-deps.js +134 -0
- package/dist/heart/daemon/ouro-bot-entry.js +1 -1
- package/dist/heart/daemon/process-manager.js +201 -0
- package/dist/heart/daemon/pulse.js +463 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +67 -16
- package/dist/heart/daemon/runtime-metadata.js +101 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +72 -3
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- package/dist/heart/daemon/socket-client.js +307 -0
- package/dist/heart/daemon/task-scheduler.js +3 -25
- package/dist/heart/daemon/thoughts.js +510 -0
- package/dist/heart/delegation.js +62 -0
- package/dist/heart/habits/habit-migration.js +181 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-scheduler.js +371 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +30 -120
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
- package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
- package/dist/heart/identity.js +163 -60
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/mcp/mcp-server.js +653 -0
- package/dist/heart/migrate-config.js +127 -0
- package/dist/heart/model-capabilities.js +59 -0
- package/dist/heart/outlook/outlook-http.js +439 -0
- package/dist/heart/outlook/outlook-read.js +1618 -0
- package/dist/heart/outlook/outlook-render.js +1032 -0
- package/dist/heart/outlook/outlook-types.js +7 -0
- package/dist/heart/outlook/outlook-view.js +194 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-failover.js +88 -0
- package/dist/heart/provider-ping.js +162 -0
- package/dist/heart/providers/anthropic-token.js +163 -0
- package/dist/heart/providers/anthropic.js +169 -46
- package/dist/heart/providers/azure.js +98 -11
- package/dist/heart/providers/error-classification.js +63 -0
- package/dist/heart/providers/github-copilot.js +136 -0
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +23 -5
- package/dist/heart/providers/openai-codex.js +33 -22
- package/dist/heart/session-activity.js +172 -0
- package/dist/heart/session-recall.js +216 -0
- package/dist/heart/start-of-turn-packet.js +339 -0
- package/dist/heart/streaming.js +36 -27
- package/dist/heart/sync.js +332 -0
- package/dist/heart/target-resolution.js +127 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/tool-activity-callbacks.js +36 -0
- package/dist/heart/tool-description.js +135 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +358 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
- package/dist/heart/versioning/ouro-version-manager.js +295 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
- package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
- package/dist/mind/associative-recall.js +135 -66
- package/dist/mind/bundle-manifest.js +8 -1
- package/dist/mind/context.js +125 -14
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +84 -96
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/first-impressions.js +14 -1
- package/dist/mind/friends/channel.js +56 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/resolver.js +37 -0
- package/dist/mind/friends/store-file.js +58 -3
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +8 -0
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +76 -9
- package/dist/mind/prompt.js +922 -109
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit.js +1 -1
- package/dist/nerves/coverage/file-completeness.js +59 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +224 -4
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
- package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
- package/dist/outlook-ui/index.html +15 -0
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +11 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +319 -0
- package/dist/repertoire/bundle-templates.js +72 -0
- package/dist/repertoire/bw-installer.js +79 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +330 -0
- package/dist/repertoire/coding/feedback.js +197 -30
- package/dist/repertoire/coding/manager.js +159 -11
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +170 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +527 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +375 -0
- package/dist/repertoire/mcp-client.js +255 -0
- package/dist/repertoire/mcp-manager.js +305 -0
- package/dist/repertoire/mcp-tools.js +63 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +14 -23
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tasks/board.js +43 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +28 -10
- package/dist/repertoire/tasks/lifecycle.js +2 -2
- package/dist/repertoire/tasks/parser.js +3 -2
- package/dist/repertoire/tasks/scanner.js +194 -37
- package/dist/repertoire/tasks/transitions.js +11 -28
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +316 -0
- package/dist/repertoire/tools-base.js +45 -771
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-bridge.js +141 -0
- package/dist/repertoire/tools-bundle.js +984 -0
- package/dist/repertoire/tools-config.js +185 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-credential.js +182 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flight.js +224 -0
- package/dist/repertoire/tools-flow.js +105 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-memory.js +374 -0
- package/dist/repertoire/tools-session.js +739 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +180 -0
- package/dist/repertoire/tools-surface.js +243 -0
- package/dist/repertoire/tools-teams.js +12 -62
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-user-profile.js +144 -0
- package/dist/repertoire/tools-vault.js +110 -0
- package/dist/repertoire/tools.js +148 -130
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +118 -0
- package/dist/repertoire/vault-setup.js +241 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/attention-queue.js +116 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +143 -9
- package/dist/senses/bluebubbles/entry.js +13 -0
- package/dist/senses/bluebubbles/inbound-log.js +113 -0
- package/dist/senses/bluebubbles/index.js +1427 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +122 -70
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
- package/dist/senses/bluebubbles/replay.js +129 -0
- package/dist/senses/bluebubbles/runtime-state.js +109 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +12 -13
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +595 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +83 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +240 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +1 -1
- package/dist/senses/cli-layout.js +187 -0
- package/dist/senses/cli.js +588 -246
- package/dist/senses/commands.js +65 -1
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +112 -19
- package/dist/senses/inner-dialog.js +633 -86
- package/dist/senses/pipeline.js +560 -0
- package/dist/senses/shared-turn.js +195 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams.js +664 -165
- package/dist/senses/trust-gate.js +112 -2
- package/package.json +14 -7
- package/skills/agent-commerce.md +106 -0
- package/skills/browser-navigation.md +110 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +81 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/subagent-installer.js +0 -134
- package/dist/senses/bluebubbles-entry.js +0 -11
- package/dist/senses/bluebubbles.js +0 -449
- package/dist/senses/debug-activity.js +0 -108
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -235
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -382
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
// Unified agent runtime entrypoint.
|
|
4
37
|
// Requires --agent before importing runtime modules that rely on identity.
|
|
@@ -7,10 +40,12 @@ if (!process.argv.includes("--agent")) {
|
|
|
7
40
|
console.error("Missing required --agent <name> argument.\nUsage: node dist/heart/agent-entry.js --agent ouroboros");
|
|
8
41
|
process.exit(1);
|
|
9
42
|
}
|
|
10
|
-
const inner_dialog_worker_1 = require("../senses/inner-dialog-worker");
|
|
11
43
|
const cli_logging_1 = require("../nerves/cli-logging");
|
|
12
44
|
(0, cli_logging_1.configureCliRuntimeLogger)("self");
|
|
13
|
-
|
|
45
|
+
// Dynamic import: agent-entry is boot-time wiring that starts a sense process.
|
|
46
|
+
// Using dynamic import avoids a static heart/ -> senses/ dependency.
|
|
47
|
+
Promise.resolve().then(() => __importStar(require("../senses/inner-dialog-worker"))).then(({ startInnerDialogWorker }) => startInnerDialogWorker())
|
|
48
|
+
.catch((error) => {
|
|
14
49
|
// eslint-disable-next-line no-console -- fatal startup guard for worker process
|
|
15
50
|
console.error(error instanceof Error ? error.message : String(error));
|
|
16
51
|
process.exit(1);
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MAX_VLM_IMAGE_BYTES = exports.MAX_ATTACHMENT_DOWNLOAD_BYTES_IMAGE = void 0;
|
|
37
|
+
exports.normalizeImageForVision = normalizeImageForVision;
|
|
38
|
+
const node_child_process_1 = require("node:child_process");
|
|
39
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
42
|
+
exports.MAX_ATTACHMENT_DOWNLOAD_BYTES_IMAGE = 32 * 1024 * 1024;
|
|
43
|
+
exports.MAX_VLM_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
44
|
+
const SAFE_VLM_MIME_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
45
|
+
const SIZE_STEPS = [3072, 2560, 2048, 1600, 1280, 1024, 768];
|
|
46
|
+
const JPEG_QUALITIES = ["best", "90", "80", "70", "60"];
|
|
47
|
+
function materializedOutputDir(agentRoot, attachmentId) {
|
|
48
|
+
return path.join(agentRoot, "state", "attachments", "materialized", attachmentId.replace(/[:/]/g, "_"));
|
|
49
|
+
}
|
|
50
|
+
function execFileText(file, args) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
(0, node_child_process_1.execFile)(file, args, (error, stdout = "", stderr = "") => {
|
|
53
|
+
if (error) {
|
|
54
|
+
reject(new Error(stderr.trim() || stdout.trim() || error.message));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
resolve(stdout);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function defaultProbeImage(input) {
|
|
62
|
+
const output = await execFileText("/usr/bin/sips", ["-g", "hasAlpha", input.sourcePath]);
|
|
63
|
+
const hasAlpha = /hasAlpha:\s+(yes|1|true)/i.test(output);
|
|
64
|
+
return { hasAlpha };
|
|
65
|
+
}
|
|
66
|
+
async function defaultRasterizeWithQuickLook(input) {
|
|
67
|
+
await fs.mkdir(input.outputDir, { recursive: true });
|
|
68
|
+
await execFileText("/usr/bin/qlmanage", ["-t", "-s", "4096", "-o", input.outputDir, input.sourcePath]);
|
|
69
|
+
const entries = await fs.readdir(input.outputDir);
|
|
70
|
+
const candidate = entries
|
|
71
|
+
.filter((entry) => entry.startsWith(path.basename(input.sourcePath, path.extname(input.sourcePath))))
|
|
72
|
+
.sort()[0];
|
|
73
|
+
if (!candidate) {
|
|
74
|
+
throw new Error("Quick Look did not produce a rasterized image");
|
|
75
|
+
}
|
|
76
|
+
return path.join(input.outputDir, candidate);
|
|
77
|
+
}
|
|
78
|
+
async function defaultEncodeVariant(input) {
|
|
79
|
+
await fs.mkdir(input.outputDir, { recursive: true });
|
|
80
|
+
const extension = input.targetFormat === "png" ? ".png" : ".jpg";
|
|
81
|
+
const basename = path.basename(input.sourcePath, path.extname(input.sourcePath));
|
|
82
|
+
const outputPath = path.join(input.outputDir, `${basename}-${input.maxEdge}-${input.targetFormat}${input.quality ? `-${input.quality}` : ""}${extension}`);
|
|
83
|
+
const args = [
|
|
84
|
+
"-s",
|
|
85
|
+
"format",
|
|
86
|
+
input.targetFormat,
|
|
87
|
+
...(input.targetFormat === "jpeg" && input.quality ? ["-s", "formatOptions", input.quality] : []),
|
|
88
|
+
"-Z",
|
|
89
|
+
String(input.maxEdge),
|
|
90
|
+
input.sourcePath,
|
|
91
|
+
"--out",
|
|
92
|
+
outputPath,
|
|
93
|
+
];
|
|
94
|
+
await execFileText("/usr/bin/sips", args);
|
|
95
|
+
const stats = await fs.stat(outputPath);
|
|
96
|
+
return {
|
|
97
|
+
path: outputPath,
|
|
98
|
+
mimeType: input.targetFormat === "png" ? "image/png" : "image/jpeg",
|
|
99
|
+
byteCount: stats.size,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function normalizeImageForVision(params) {
|
|
103
|
+
const maxVlmBytes = params.maxVlmBytes ?? exports.MAX_VLM_IMAGE_BYTES;
|
|
104
|
+
const originalMimeType = params.attachment.mimeType?.trim().toLowerCase();
|
|
105
|
+
const originalByteCount = params.attachment.byteCount;
|
|
106
|
+
const outputDir = materializedOutputDir(params.agentRoot, params.attachment.id);
|
|
107
|
+
if (originalMimeType
|
|
108
|
+
&& SAFE_VLM_MIME_TYPES.has(originalMimeType)
|
|
109
|
+
&& typeof originalByteCount === "number"
|
|
110
|
+
&& originalByteCount <= maxVlmBytes) {
|
|
111
|
+
(0, runtime_1.emitNervesEvent)({
|
|
112
|
+
component: "engine",
|
|
113
|
+
event: "engine.attachment_normalization_passthrough",
|
|
114
|
+
message: "attachment image normalization updated",
|
|
115
|
+
meta: {
|
|
116
|
+
attachmentId: params.attachment.id,
|
|
117
|
+
mimeType: originalMimeType,
|
|
118
|
+
byteCount: originalByteCount,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
path: path.resolve(params.sourcePath),
|
|
123
|
+
mimeType: originalMimeType,
|
|
124
|
+
byteCount: originalByteCount,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const probeImage = params.probeImage ?? defaultProbeImage;
|
|
128
|
+
const rasterizeWithQuickLook = params.rasterizeWithQuickLook ?? defaultRasterizeWithQuickLook;
|
|
129
|
+
const encodeVariant = params.encodeVariant ?? defaultEncodeVariant;
|
|
130
|
+
let workingSourcePath = path.resolve(params.sourcePath);
|
|
131
|
+
let probe;
|
|
132
|
+
try {
|
|
133
|
+
probe = await probeImage({ sourcePath: workingSourcePath });
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
(0, runtime_1.emitNervesEvent)({
|
|
137
|
+
component: "engine",
|
|
138
|
+
event: "engine.attachment_normalization_rasterize",
|
|
139
|
+
message: "attachment image normalization updated",
|
|
140
|
+
meta: {
|
|
141
|
+
attachmentId: params.attachment.id,
|
|
142
|
+
sourcePath: workingSourcePath,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
workingSourcePath = await rasterizeWithQuickLook({
|
|
146
|
+
sourcePath: workingSourcePath,
|
|
147
|
+
outputDir,
|
|
148
|
+
});
|
|
149
|
+
probe = await probeImage({ sourcePath: workingSourcePath });
|
|
150
|
+
}
|
|
151
|
+
const targetFormats = probe.hasAlpha ? ["png", "jpeg"] : ["jpeg"];
|
|
152
|
+
for (const targetFormat of targetFormats) {
|
|
153
|
+
for (const maxEdge of SIZE_STEPS) {
|
|
154
|
+
const qualities = targetFormat === "jpeg" ? JPEG_QUALITIES : [undefined];
|
|
155
|
+
for (const quality of qualities) {
|
|
156
|
+
const variant = await encodeVariant({
|
|
157
|
+
sourcePath: workingSourcePath,
|
|
158
|
+
outputDir,
|
|
159
|
+
targetFormat,
|
|
160
|
+
maxEdge,
|
|
161
|
+
...(quality ? { quality } : {}),
|
|
162
|
+
});
|
|
163
|
+
if ((variant.byteCount ?? Number.POSITIVE_INFINITY) <= maxVlmBytes) {
|
|
164
|
+
(0, runtime_1.emitNervesEvent)({
|
|
165
|
+
component: "engine",
|
|
166
|
+
event: "engine.attachment_normalization_succeeded",
|
|
167
|
+
message: "attachment image normalization updated",
|
|
168
|
+
meta: {
|
|
169
|
+
attachmentId: params.attachment.id,
|
|
170
|
+
sourceMimeType: originalMimeType ?? "unknown",
|
|
171
|
+
outputMimeType: variant.mimeType ?? `image/${targetFormat}`,
|
|
172
|
+
byteCount: variant.byteCount,
|
|
173
|
+
maxEdge,
|
|
174
|
+
quality: quality ?? null,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
return variant;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
(0, runtime_1.emitNervesEvent)({
|
|
183
|
+
component: "engine",
|
|
184
|
+
event: "engine.attachment_normalization_failed",
|
|
185
|
+
message: "attachment image normalization updated",
|
|
186
|
+
meta: {
|
|
187
|
+
attachmentId: params.attachment.id,
|
|
188
|
+
sourceMimeType: originalMimeType ?? "unknown",
|
|
189
|
+
sourceByteCount: originalByteCount ?? null,
|
|
190
|
+
maxVlmBytes,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
throw new Error(`Attachment ${params.attachment.id} could not be normalized under the VLM byte budget`);
|
|
194
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.persistBlueBubblesAttachmentSource = persistBlueBubblesAttachmentSource;
|
|
37
|
+
exports.materializeAttachment = materializeAttachment;
|
|
38
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
41
|
+
const identity_1 = require("../identity");
|
|
42
|
+
const config_1 = require("../config");
|
|
43
|
+
const image_normalize_1 = require("./image-normalize");
|
|
44
|
+
const store_1 = require("./store");
|
|
45
|
+
const types_1 = require("./types");
|
|
46
|
+
const attachment_download_1 = require("../../senses/bluebubbles/attachment-download");
|
|
47
|
+
async function ensureReadableFile(filePath) {
|
|
48
|
+
await fs.access(filePath);
|
|
49
|
+
}
|
|
50
|
+
function extensionForAttachment(displayName, mimeType) {
|
|
51
|
+
const explicit = path.extname(displayName).trim();
|
|
52
|
+
if (explicit)
|
|
53
|
+
return explicit;
|
|
54
|
+
switch (mimeType?.trim().toLowerCase()) {
|
|
55
|
+
case "image/jpeg":
|
|
56
|
+
return ".jpg";
|
|
57
|
+
case "image/png":
|
|
58
|
+
return ".png";
|
|
59
|
+
case "image/webp":
|
|
60
|
+
return ".webp";
|
|
61
|
+
case "image/gif":
|
|
62
|
+
return ".gif";
|
|
63
|
+
case "image/tiff":
|
|
64
|
+
return ".tiff";
|
|
65
|
+
case "image/bmp":
|
|
66
|
+
return ".bmp";
|
|
67
|
+
case "image/heic":
|
|
68
|
+
return ".heic";
|
|
69
|
+
case "application/pdf":
|
|
70
|
+
return ".pdf";
|
|
71
|
+
case "audio/mp3":
|
|
72
|
+
case "audio/mpeg":
|
|
73
|
+
return ".mp3";
|
|
74
|
+
case "audio/mp4":
|
|
75
|
+
return ".m4a";
|
|
76
|
+
default:
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function originalStoragePath(agentRoot, attachment, mimeType) {
|
|
81
|
+
const extension = extensionForAttachment(attachment.displayName, mimeType ?? attachment.mimeType);
|
|
82
|
+
return path.join(agentRoot, "state", "attachments", "materialized", attachment.source, attachment.sourceId, `original${extension}`);
|
|
83
|
+
}
|
|
84
|
+
function buildOriginalMaterializedAttachment(attachment, filePath, mimeType, byteCount) {
|
|
85
|
+
return {
|
|
86
|
+
attachmentId: attachment.id,
|
|
87
|
+
variant: "original",
|
|
88
|
+
path: filePath,
|
|
89
|
+
displayName: attachment.displayName,
|
|
90
|
+
mimeType: mimeType ?? attachment.mimeType,
|
|
91
|
+
byteCount: byteCount ?? attachment.byteCount,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async function persistBlueBubblesAttachmentSource(agentName, attachment, input, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
95
|
+
const targetPath = originalStoragePath(agentRoot, attachment, input.mimeType);
|
|
96
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
97
|
+
await fs.writeFile(targetPath, input.buffer);
|
|
98
|
+
const updated = (0, types_1.buildBlueBubblesAttachmentRecord)({
|
|
99
|
+
...attachment.sourceData,
|
|
100
|
+
mimeType: input.mimeType ?? attachment.sourceData.mimeType,
|
|
101
|
+
totalBytes: input.byteCount ?? attachment.byteCount,
|
|
102
|
+
}, attachment.createdAt, {
|
|
103
|
+
localPath: targetPath,
|
|
104
|
+
mimeType: input.mimeType ?? attachment.mimeType,
|
|
105
|
+
byteCount: input.byteCount ?? attachment.byteCount,
|
|
106
|
+
});
|
|
107
|
+
updated.lastSeenAt = Date.now();
|
|
108
|
+
(0, store_1.rememberRecentAttachment)(agentName, updated, agentRoot);
|
|
109
|
+
(0, runtime_1.emitNervesEvent)({
|
|
110
|
+
component: "engine",
|
|
111
|
+
event: "engine.attachment_source_persisted",
|
|
112
|
+
message: "attachment materialization updated",
|
|
113
|
+
meta: {
|
|
114
|
+
attachmentId: attachment.id,
|
|
115
|
+
source: attachment.source,
|
|
116
|
+
mimeType: updated.mimeType,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
return updated;
|
|
120
|
+
}
|
|
121
|
+
async function materializeOriginalAttachment(agentName, attachment, agentRoot) {
|
|
122
|
+
void agentName;
|
|
123
|
+
void agentRoot;
|
|
124
|
+
switch (attachment.source) {
|
|
125
|
+
case "cli-local-file": {
|
|
126
|
+
await ensureReadableFile(attachment.sourceData.path);
|
|
127
|
+
(0, runtime_1.emitNervesEvent)({
|
|
128
|
+
component: "engine",
|
|
129
|
+
event: "engine.attachment_materialized",
|
|
130
|
+
message: "attachment materialization updated",
|
|
131
|
+
meta: {
|
|
132
|
+
attachmentId: attachment.id,
|
|
133
|
+
variant: "original",
|
|
134
|
+
source: attachment.source,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
attachmentId: attachment.id,
|
|
139
|
+
variant: "original",
|
|
140
|
+
path: attachment.sourceData.path,
|
|
141
|
+
displayName: attachment.displayName,
|
|
142
|
+
mimeType: attachment.mimeType,
|
|
143
|
+
byteCount: attachment.byteCount,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
case "bluebubbles": {
|
|
147
|
+
const localPath = attachment.sourceData.localPath?.trim();
|
|
148
|
+
if (localPath) {
|
|
149
|
+
await ensureReadableFile(localPath);
|
|
150
|
+
(0, runtime_1.emitNervesEvent)({
|
|
151
|
+
component: "engine",
|
|
152
|
+
event: "engine.attachment_materialized",
|
|
153
|
+
message: "attachment materialization updated",
|
|
154
|
+
meta: {
|
|
155
|
+
attachmentId: attachment.id,
|
|
156
|
+
variant: "original",
|
|
157
|
+
source: attachment.source,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
return buildOriginalMaterializedAttachment(attachment, localPath);
|
|
161
|
+
}
|
|
162
|
+
const fallbackPath = originalStoragePath(agentRoot, attachment);
|
|
163
|
+
try {
|
|
164
|
+
await ensureReadableFile(fallbackPath);
|
|
165
|
+
return buildOriginalMaterializedAttachment(attachment, fallbackPath);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
const config = (0, config_1.getBlueBubblesConfig)();
|
|
169
|
+
const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
|
|
170
|
+
const downloaded = await (0, attachment_download_1.downloadBlueBubblesAttachment)(attachment.sourceData, config, channelConfig);
|
|
171
|
+
const updated = await persistBlueBubblesAttachmentSource(agentName, attachment, {
|
|
172
|
+
buffer: downloaded.buffer,
|
|
173
|
+
mimeType: downloaded.contentType,
|
|
174
|
+
byteCount: downloaded.buffer.length,
|
|
175
|
+
}, agentRoot);
|
|
176
|
+
(0, runtime_1.emitNervesEvent)({
|
|
177
|
+
component: "engine",
|
|
178
|
+
event: "engine.attachment_materialized",
|
|
179
|
+
message: "attachment materialization updated",
|
|
180
|
+
meta: {
|
|
181
|
+
attachmentId: attachment.id,
|
|
182
|
+
variant: "original",
|
|
183
|
+
source: attachment.source,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
return buildOriginalMaterializedAttachment(updated, updated.sourceData.localPath, downloaded.contentType ?? updated.mimeType, downloaded.buffer.length);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function materializeAttachment(agentName, attachmentId, options = {}) {
|
|
192
|
+
const agentRoot = options.agentRoot ?? (0, identity_1.getAgentRoot)(agentName);
|
|
193
|
+
const variant = options.variant ?? "original";
|
|
194
|
+
const attachment = (0, store_1.getRecentAttachment)(agentName, attachmentId, agentRoot);
|
|
195
|
+
if (!attachment) {
|
|
196
|
+
throw new Error(`Attachment not found: ${attachmentId}`);
|
|
197
|
+
}
|
|
198
|
+
if (variant === "original") {
|
|
199
|
+
return await materializeOriginalAttachment(agentName, attachment, agentRoot);
|
|
200
|
+
}
|
|
201
|
+
if (attachment.kind !== "image") {
|
|
202
|
+
throw new Error(`Attachment ${attachmentId} is not an image and cannot produce a vision_safe variant`);
|
|
203
|
+
}
|
|
204
|
+
const original = await materializeOriginalAttachment(agentName, attachment, agentRoot);
|
|
205
|
+
const normalizeImage = options.normalizeImage ?? image_normalize_1.normalizeImageForVision;
|
|
206
|
+
const normalized = await normalizeImage({
|
|
207
|
+
attachment,
|
|
208
|
+
sourcePath: original.path,
|
|
209
|
+
agentName,
|
|
210
|
+
agentRoot,
|
|
211
|
+
});
|
|
212
|
+
(0, runtime_1.emitNervesEvent)({
|
|
213
|
+
component: "engine",
|
|
214
|
+
event: "engine.attachment_materialized",
|
|
215
|
+
message: "attachment materialization updated",
|
|
216
|
+
meta: {
|
|
217
|
+
attachmentId: attachment.id,
|
|
218
|
+
variant: "vision_safe",
|
|
219
|
+
source: attachment.source,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
attachmentId: attachment.id,
|
|
224
|
+
variant: "vision_safe",
|
|
225
|
+
path: path.resolve(normalized.path),
|
|
226
|
+
displayName: attachment.displayName,
|
|
227
|
+
mimeType: normalized.mimeType ?? attachment.mimeType,
|
|
228
|
+
byteCount: normalized.byteCount,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderAttachmentBlock = renderAttachmentBlock;
|
|
4
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
5
|
+
function formatBytes(byteCount) {
|
|
6
|
+
if (typeof byteCount !== "number" || !Number.isFinite(byteCount) || byteCount < 0) {
|
|
7
|
+
return "unknown size";
|
|
8
|
+
}
|
|
9
|
+
if (byteCount >= 1024 * 1024) {
|
|
10
|
+
return `${(byteCount / (1024 * 1024)).toFixed(1)} MB`;
|
|
11
|
+
}
|
|
12
|
+
if (byteCount >= 1024) {
|
|
13
|
+
return `${Math.round(byteCount / 1024)} KB`;
|
|
14
|
+
}
|
|
15
|
+
return `${byteCount} B`;
|
|
16
|
+
}
|
|
17
|
+
function renderAttachmentBlock(attachments) {
|
|
18
|
+
if (attachments.length === 0)
|
|
19
|
+
return "";
|
|
20
|
+
const body = attachments.map((attachment) => `- ${attachment.id} | ${attachment.kind} | ${attachment.displayName} | ${attachment.mimeType ?? "unknown mime"} | ${formatBytes(attachment.byteCount)}`);
|
|
21
|
+
const rendered = ["[attachments]", ...body].join("\n");
|
|
22
|
+
(0, runtime_1.emitNervesEvent)({
|
|
23
|
+
component: "engine",
|
|
24
|
+
event: "engine.attachment_block_rendered",
|
|
25
|
+
message: "attachment transcript block rendered",
|
|
26
|
+
meta: { count: attachments.length },
|
|
27
|
+
});
|
|
28
|
+
return rendered;
|
|
29
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MAX_RECENT_ATTACHMENTS = void 0;
|
|
37
|
+
exports.getRecentAttachmentsPath = getRecentAttachmentsPath;
|
|
38
|
+
exports.readRecentAttachments = readRecentAttachments;
|
|
39
|
+
exports.rememberRecentAttachment = rememberRecentAttachment;
|
|
40
|
+
exports.getRecentAttachment = getRecentAttachment;
|
|
41
|
+
exports.listRecentAttachments = listRecentAttachments;
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
45
|
+
const identity_1 = require("../identity");
|
|
46
|
+
exports.MAX_RECENT_ATTACHMENTS = 100;
|
|
47
|
+
function getRecentAttachmentsPath(agentName, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
48
|
+
return path.join(agentRoot, "state", "attachments", "recent.json");
|
|
49
|
+
}
|
|
50
|
+
function readRecentAttachments(agentName, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
51
|
+
const targetPath = getRecentAttachmentsPath(agentName, agentRoot);
|
|
52
|
+
if (!fs.existsSync(targetPath)) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(fs.readFileSync(targetPath, "utf-8"));
|
|
57
|
+
if (!Array.isArray(parsed)) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return parsed;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
(0, runtime_1.emitNervesEvent)({
|
|
64
|
+
level: "warn",
|
|
65
|
+
component: "engine",
|
|
66
|
+
event: "engine.attachment_store_read_error",
|
|
67
|
+
message: "failed to read recent attachments store",
|
|
68
|
+
meta: {
|
|
69
|
+
path: targetPath,
|
|
70
|
+
reason: String(error),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function writeRecentAttachments(agentName, agentRoot, attachments) {
|
|
77
|
+
const targetPath = getRecentAttachmentsPath(agentName, agentRoot);
|
|
78
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
79
|
+
fs.writeFileSync(targetPath, JSON.stringify(attachments, null, 2), "utf-8");
|
|
80
|
+
}
|
|
81
|
+
function rememberRecentAttachment(agentName, attachment, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
82
|
+
const deduped = readRecentAttachments(agentName, agentRoot).filter((entry) => entry.id !== attachment.id);
|
|
83
|
+
const updated = [attachment, ...deduped]
|
|
84
|
+
.sort((a, b) => b.lastSeenAt - a.lastSeenAt)
|
|
85
|
+
.slice(0, exports.MAX_RECENT_ATTACHMENTS);
|
|
86
|
+
writeRecentAttachments(agentName, agentRoot, updated);
|
|
87
|
+
(0, runtime_1.emitNervesEvent)({
|
|
88
|
+
component: "engine",
|
|
89
|
+
event: "engine.attachment_store_updated",
|
|
90
|
+
message: "recent attachment stored",
|
|
91
|
+
meta: { attachmentId: attachment.id, source: attachment.source, kind: attachment.kind },
|
|
92
|
+
});
|
|
93
|
+
return attachment;
|
|
94
|
+
}
|
|
95
|
+
function getRecentAttachment(agentName, attachmentId, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
96
|
+
return readRecentAttachments(agentName, agentRoot).find((entry) => entry.id === attachmentId) ?? null;
|
|
97
|
+
}
|
|
98
|
+
function listRecentAttachments(agentName, options = {}, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
|
|
99
|
+
const limit = Math.max(1, options.limit ?? exports.MAX_RECENT_ATTACHMENTS);
|
|
100
|
+
return readRecentAttachments(agentName, agentRoot)
|
|
101
|
+
.filter((entry) => !options.kind || entry.kind === options.kind)
|
|
102
|
+
.slice(0, limit);
|
|
103
|
+
}
|