@desplega.ai/agent-swarm 1.131.1 → 1.133.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/README.md +2 -2
- package/dist/{actions-jgcy477k.js → actions-cskpayd7.js} +11 -9
- package/dist/{anthropic-messages-rjmd2e7n.js → anthropic-messages-tpxtbx7b.js} +28 -12
- package/dist/{app-5da78bd4.js → app-ang77nbb.js} +8 -6
- package/dist/{assistant-f2vkk1hj.js → assistant-b4exebdw.js} +16 -13
- package/dist/{azure-openai-responses-c0yjmbfd.js → azure-openai-responses-m3921t4y.js} +8 -8
- package/dist/{boot-reembed-q7mp8hcr.js → boot-reembed-ps2aftpb.js} +9 -7
- package/dist/{boot-reembed-xmw8wcx6.js → boot-reembed-znyk3nxb.js} +10 -8
- package/dist/{boot-scrub-logs-dsqrv79n.js → boot-scrub-logs-2ax3xgz1.js} +7 -5
- package/dist/{claude-adapter-q6x7yspx.js → claude-adapter-3ct8kgxw.js} +13 -9
- package/dist/{claude-managed-adapter-wsg37bt8.js → claude-managed-adapter-akx4ntf2.js} +2 -2
- package/dist/{cli-114fvtmj.js → cli-13w2hwkh.js} +1 -1
- package/dist/{cli-4rkfg1wx.js → cli-1532szb1.js} +8 -6
- package/dist/{cli-g74vpjp2.js → cli-23d3rseb.js} +33 -17
- package/dist/{cli-3ty0t082.js → cli-2a75z9c5.js} +196 -7
- package/dist/{cli-pxfxkx5m.js → cli-2t30rj0d.js} +1 -1
- package/dist/{cli-rgrfzg8z.js → cli-3c3tdgab.js} +10 -10
- package/dist/{cli-6dp3ydxa.js → cli-3zzxa9jz.js} +15 -11
- package/dist/{cli-2f07m0xr.js → cli-4k6233gc.js} +1 -1
- package/dist/{cli-t8d349cy.js → cli-5p2tz05r.js} +2 -2
- package/dist/{cli-w2wxd56v.js → cli-5z2yhzvd.js} +127 -49
- package/dist/{cli-kd1ck4rx.js → cli-6zfq31nj.js} +9 -3
- package/dist/{cli-er3a4bb0.js → cli-8m9de10a.js} +6 -1
- package/dist/{cli-gm9cbhbq.js → cli-8t14vg9w.js} +27 -8
- package/dist/{cli-ccf9vy7q.js → cli-9nfc2es8.js} +6 -6
- package/dist/{cli-ycrnynpw.js → cli-9ta3pwms.js} +11 -4
- package/dist/{cli-7dm2zqy2.js → cli-avr0ns7z.js} +2 -2
- package/dist/{cli-n6h8qt8n.js → cli-c897wyhw.js} +12 -7
- package/dist/{cli-gecy3z2s.js → cli-dgk20ft7.js} +4 -4
- package/dist/cli-et1bbwqf.js +13 -0
- package/dist/{cli-bqw0mt1n.js → cli-f5w27pj3.js} +3 -3
- package/dist/{cli-2wadx7p2.js → cli-f8dre4bz.js} +2 -2
- package/dist/{cli-6pcz9h15.js → cli-ftwpv451.js} +170 -387
- package/dist/{cli-nrkkknat.js → cli-g854s2dw.js} +1 -1
- package/dist/{cli-793jvbsh.js → cli-ggmdxeqa.js} +13 -8
- package/dist/cli-hkwfe3qj.js +530 -0
- package/dist/{cli-5dsbcjjw.js → cli-jqwnqx9m.js} +1 -1
- package/dist/{cli-9dr5qzc0.js → cli-ny122vh4.js} +21 -10
- package/dist/{cli-sy7jk3tx.js → cli-pvzqhbs9.js} +2 -2
- package/dist/cli-pzq5rjym.js +15 -0
- package/dist/{cli-xpxde7rm.js → cli-qes8ef67.js} +48 -30
- package/dist/{cli-sajgpkqg.js → cli-qs9hhsvb.js} +1723 -325
- package/dist/cli-qys3rhhz.js +27 -0
- package/dist/{cli-se2p6rkb.js → cli-r6tpm37h.js} +2 -2
- package/dist/{cli-g1re8r05.js → cli-rch80c76.js} +2 -2
- package/dist/{cli-0258203w.js → cli-rpp0x4zy.js} +137 -17
- package/dist/{cli-5n6e5yfn.js → cli-s1k0wxhe.js} +12 -7
- package/dist/{cli-aca5pz9f.js → cli-sfd9v7sj.js} +1 -1
- package/dist/{cli-2rk0cx7s.js → cli-sh3ytsyj.js} +49 -39
- package/dist/{cli-zsspvvm2.js → cli-w1mp9jy7.js} +1 -1
- package/dist/{cli-6dpytdr2.js → cli-xdb4mpnp.js} +2 -2
- package/dist/{cli-57khth04.js → cli-xmyqv00z.js} +120 -4
- package/dist/{cli-jbcva0xj.js → cli-xv8t8p3c.js} +56 -31
- package/dist/{cli-f1am9szv.js → cli-xxv5pn4f.js} +1 -1
- package/dist/{cli-jevgrb4w.js → cli-y08jvxzx.js} +601 -140
- package/dist/{cli-50vbt00w.js → cli-zfbf3srj.js} +650 -245
- package/dist/{cli-ygrbmjja.js → cli-zmq89k34.js} +6 -6
- package/dist/cli.js +22 -22
- package/dist/{codex-adapter-htjkn22b.js → codex-adapter-bef93pq4.js} +9 -7
- package/dist/{codex-hook-hq54t9ft.js → codex-hook-e8dba65p.js} +3 -2
- package/dist/{codex-session-runner-wjfc7smz.js → codex-session-runner-5pkxys7x.js} +9 -7
- package/dist/{commands-xhrfwqsk.js → commands-e23s1bff.js} +9 -7
- package/dist/{db-anvwb22f.js → db-m3nabatn.js} +17 -5
- package/dist/{google-generative-ai-hysrd8qx.js → google-generative-ai-8maw55xh.js} +11 -8
- package/dist/{google-vertex-p5arrga0.js → google-vertex-8vjqmx8g.js} +11 -8
- package/dist/{handlers-b9kbc621.js → handlers-akazedvr.js} +16 -13
- package/dist/{hook-xkvn6c5h.js → hook-ze4cpf0v.js} +55 -41
- package/dist/{hook-cgk4wxmx.js → hook-zfqyyenw.js} +10 -7
- package/dist/{http-9xh6ta4r.js → http-sja0n6kw.js} +608 -147
- package/dist/index-0gr8vd6k.js +39 -0
- package/dist/{index-eaxyqcmj.js → index-354vkhdv.js} +154 -74
- package/dist/{index-070v4eyb.js → index-5qthek5t.js} +2 -3
- package/dist/{index-25wjsdv2.js → index-95t3cqq5.js} +16 -14
- package/dist/{index-9znhar3x.js → index-sea66619.js} +3 -4
- package/dist/{index-ywds4812.js → index-vpn36mma.js} +15 -13
- package/dist/{keepalive-vc7s2aa6.js → keepalive-3sp3meqj.js} +16 -10
- package/dist/{lead-r2yqfmx7.js → lead-mefeewkf.js} +39 -36
- package/dist/{maintenance-mw70k468.js → maintenance-8tbrbjfg.js} +10 -8
- package/dist/mistral-conversations-00zrp7g4.js +717 -0
- package/dist/{oauth-refresh-sweep-yecgjpk4.js → oauth-refresh-sweep-srjwjz6m.js} +8 -6
- package/dist/{onboard-xj0f73f9.js → onboard-mt2tgyjg.js} +7 -7
- package/dist/{openai-codex-responses-5g27pd6f.js → openai-codex-responses-map32h2s.js} +18 -18
- package/dist/{openai-completions-3vkmfz2a.js → openai-completions-w871b1cq.js} +12 -11
- package/dist/{openai-responses-dg4t7j7a.js → openai-responses-b0j7xnw8.js} +15 -12
- package/dist/{opencode-adapter-1gm38aba.js → opencode-adapter-b39jefcj.js} +5 -3
- package/dist/{openrouter-images-g3gm8931.js → openrouter-images-srfkywy0.js} +4 -4
- package/dist/{otel-impl-nxg0n0b3.js → otel-impl-z6pxt3j9.js} +224 -9
- package/dist/{pi-mono-adapter-4g5kby31.js → pi-mono-adapter-btvqmj58.js} +1138 -408
- package/dist/{pricing-refresh-2cn6effr.js → pricing-refresh-kyq8cezh.js} +9 -7
- package/dist/{rbac-roles-1hcxdtg7.js → rbac-roles-3ryfrfna.js} +8 -6
- package/dist/{rbac-roles-vynday5g.js → rbac-roles-6qfvbee1.js} +9 -7
- package/dist/{render-v2-tc0bh8kk.js → render-v2-p61ppjey.js} +8 -6
- package/dist/{seed-pricing-8kceb43f.js → seed-pricing-j56bbj4y.js} +8 -6
- package/dist/{setup-46xtgq3c.js → setup-tpr6c1kn.js} +2 -2
- package/dist/{worker-qrbz6hmv.js → worker-9w1v0mbb.js} +39 -36
- package/openapi.json +542 -16
- package/package.json +6 -6
- package/src/be/budget-refusal-notify.ts +14 -7
- package/src/be/db-queries/task-artifacts.ts +182 -0
- package/src/be/db.ts +783 -169
- package/src/be/events.ts +5 -0
- package/src/be/migrations/131_session_logs_created_at_index.sql +2 -0
- package/src/be/migrations/132_multi_runtime_instances.sql +44 -0
- package/src/be/migrations/133_workflow_run_trigger_type.sql +12 -0
- package/src/be/migrations/135_backfill_task_pull_request_attachments.sql +228 -0
- package/src/be/migrations/136_task_requester_provenance.sql +37 -0
- package/src/be/migrations/137_memory_retrieval_composite_index.sql +1 -0
- package/src/be/multi-runtime.ts +430 -0
- package/src/be/scripts/extract-schema.ts +3 -1
- package/src/be/scripts/typecheck.ts +3 -2
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/steering.ts +1 -1
- package/src/be/swarm-config-guard.ts +18 -0
- package/src/commands/credential-wait.ts +54 -0
- package/src/commands/onboard/steps/core-credentials.tsx +1 -1
- package/src/commands/onboard/steps/custom-templates.tsx +1 -1
- package/src/commands/onboard/steps/harness-credentials.tsx +1 -1
- package/src/commands/onboard/steps/health-check.tsx +1 -1
- package/src/commands/onboard/steps/start.tsx +1 -1
- package/src/commands/profile-sync-audit.ts +56 -0
- package/src/commands/profile-sync.ts +287 -15
- package/src/commands/provider-credentials.ts +46 -19
- package/src/commands/runner.ts +196 -33
- package/src/commands/templates.ts +22 -0
- package/src/github/handlers.ts +55 -9
- package/src/heartbeat/heartbeat.ts +71 -12
- package/src/hooks/hook.ts +49 -33
- package/src/http/active-sessions.ts +11 -1
- package/src/http/agents.ts +261 -30
- package/src/http/all-routes.ts +1 -0
- package/src/http/config.ts +13 -2
- package/src/http/core.ts +102 -4
- package/src/http/db-query-bounded.ts +313 -0
- package/src/http/db-query-shared.ts +249 -0
- package/src/http/db-query.ts +54 -42
- package/src/http/events.ts +2 -0
- package/src/http/index.ts +22 -2
- package/src/http/mcp-bridge.ts +37 -3
- package/src/http/mcp.ts +12 -0
- package/src/http/memory.ts +13 -2
- package/src/http/openapi.ts +1 -0
- package/src/http/poll.ts +70 -27
- package/src/http/route-def.ts +43 -9
- package/src/http/schedules.ts +2 -2
- package/src/http/scripts.ts +10 -1
- package/src/http/session-data.ts +44 -0
- package/src/http/tasks.ts +2 -2
- package/src/http/users.ts +74 -52
- package/src/http/webhooks.ts +5 -2
- package/src/http/workflows.ts +1 -4
- package/src/integrations/kapso/inbound.ts +1 -1
- package/src/jira/outbound.ts +39 -8
- package/src/jira/webhook-lifecycle.ts +13 -2
- package/src/linear/outbound.ts +43 -10
- package/src/oauth/keepalive.ts +13 -2
- package/src/prompts/base-prompt.ts +1 -1
- package/src/prompts/session-templates.ts +45 -7
- package/src/providers/claude-adapter.ts +6 -0
- package/src/providers/codex-adapter.ts +6 -0
- package/src/providers/opencode-adapter.ts +6 -0
- package/src/providers/pi-mono-adapter.ts +8 -0
- package/src/providers/pricing-sources.md +24 -0
- package/src/queue-stall-alarm.ts +216 -0
- package/src/scheduler/scheduler.ts +7 -0
- package/src/script-workflows/executor.ts +2 -1
- package/src/scripts-runtime/executors/native.ts +2 -1
- package/src/scripts-runtime/executors/types.ts +5 -0
- package/src/scripts-runtime/loader.ts +5 -0
- package/src/scripts-runtime/swarm-config.ts +8 -0
- package/src/scripts-runtime/swarm-sdk.ts +7 -0
- package/src/scripts-runtime/types/stdlib.d.ts +1 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
- package/src/tests/budget-claim-gate.test.ts +20 -0
- package/src/tests/claude-adapter.test.ts +32 -0
- package/src/tests/codex-adapter.test.ts +30 -0
- package/src/tests/create-task-validation.test.ts +128 -0
- package/src/tests/credential-wait.test.ts +67 -1
- package/src/tests/db-query.test.ts +711 -2
- package/src/tests/http-api-integration.test.ts +81 -0
- package/src/tests/http-users.test.ts +166 -1
- package/src/tests/identity-field-budget.test.ts +176 -0
- package/src/tests/mcp-tools-user.test.ts +34 -0
- package/src/tests/mcp-user-route.test.ts +17 -0
- package/src/tests/metrics-http.test.ts +44 -0
- package/src/tests/multi-runtime-registration.test.ts +2703 -0
- package/src/tests/openapi-response-contract.test.ts +24 -0
- package/src/tests/openapi-route-headers.test.ts +83 -0
- package/src/tests/opencode-adapter.test.ts +40 -0
- package/src/tests/outbound-listener-rejection.test.ts +138 -0
- package/src/tests/pi-mono-adapter.test.ts +98 -0
- package/src/tests/profile-sync-warning.test.ts +277 -0
- package/src/tests/profile-sync.test.ts +232 -6
- package/src/tests/prompt-template-session.test.ts +32 -3
- package/src/tests/queue-stall-alarm.test.ts +226 -0
- package/src/tests/requester-comms.test.ts +32 -0
- package/src/tests/runner-requester-profile.test.ts +38 -0
- package/src/tests/schedule-target-type.test.ts +38 -0
- package/src/tests/script-connections.test.ts +13 -1
- package/src/tests/scripts-runtime-identity.test.ts +375 -0
- package/src/tests/scripts-runtime.test.ts +4 -3
- package/src/tests/sdk-allowlist.test.ts +47 -0
- package/src/tests/send-task-requested-by.test.ts +9 -0
- package/src/tests/session-costs.test.ts +506 -1
- package/src/tests/shutdown-error-scrubbing.test.ts +92 -0
- package/src/tests/steering-core.test.ts +28 -0
- package/src/tests/task-artifacts.test.ts +386 -0
- package/src/tests/task-attachments-schema.test.ts +17 -1
- package/src/tests/task-completion-idempotency.test.ts +57 -0
- package/src/tests/task-pull-request-backfill-migration.test.ts +321 -0
- package/src/tests/update-profile-api.test.ts +67 -39
- package/src/tests/update-profile-auth.test.ts +48 -4
- package/src/tests/user-attribution-migration.test.ts +54 -0
- package/src/tests/user-identity.test.ts +72 -0
- package/src/tests/workflow-async-v2.test.ts +39 -1
- package/src/tests/workflow-http-v2.test.ts +3 -2
- package/src/tests/workflow-mcp-trigger-schema.test.ts +52 -3
- package/src/tests/workflow-retry-v2.test.ts +45 -1
- package/src/tools/db-query.ts +18 -8
- package/src/tools/get-task-details.ts +24 -3
- package/src/tools/manage-user.ts +36 -3
- package/src/tools/poll-task.ts +93 -14
- package/src/tools/script-common.ts +5 -0
- package/src/tools/send-task.ts +1 -4
- package/src/tools/store-progress.ts +13 -2
- package/src/tools/swarm-config/delete-config.ts +9 -0
- package/src/tools/swarm-config/set-config.ts +3 -2
- package/src/tools/task-action.ts +30 -0
- package/src/tools/task-tool-ctx.ts +8 -1
- package/src/tools/update-profile.ts +16 -21
- package/src/tools/utils.ts +5 -0
- package/src/tools/workflows/trigger-workflow.ts +7 -1
- package/src/types.ts +165 -1
- package/src/utils/github-pull-request.ts +76 -0
- package/src/utils/identity-field-budget.ts +73 -0
- package/src/utils/multi-runtime.ts +20 -0
- package/src/utils/requester-comms.ts +24 -0
- package/src/workflows/engine.ts +22 -2
- package/src/workflows/resume.ts +19 -11
- package/src/workflows/retry-poller.ts +1 -0
- package/src/workflows/triggers.ts +4 -0
- package/templates/skills/db-query-guidance/config.json +14 -0
- package/templates/skills/db-query-guidance/content.md +57 -0
- package/dist/cli-3te4jdkm.js +0 -225
- package/dist/cli-bmze986d.js +0 -7
- package/dist/cli-kh3ba2zf.js +0 -607
- package/dist/index-vg4snay4.js +0 -36
- package/dist/mistral-conversations-81fwav0j.js +0 -30578
- package/dist/otel-nqa12wf3.js +0 -3149
- package/dist/{cli-wz9115x0.js → cli-zr9q011v.js} +6 -6
- package/dist/{pi-messages-tqj8q6b9.js → pi-messages-sssy32x4.js} +3 -3
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm
|
|
3
|
+
} from "./cli-p9swy5t3.js";
|
|
4
|
+
|
|
5
|
+
// src/utils/env-flag.ts
|
|
6
|
+
function parseEnvFlag(raw, defaultValue) {
|
|
7
|
+
if (raw === undefined || raw === null)
|
|
8
|
+
return defaultValue;
|
|
9
|
+
const normalized = raw.trim().toLowerCase();
|
|
10
|
+
if (normalized === "")
|
|
11
|
+
return defaultValue;
|
|
12
|
+
if (TRUTHY.has(normalized))
|
|
13
|
+
return true;
|
|
14
|
+
if (FALSY.has(normalized))
|
|
15
|
+
return false;
|
|
16
|
+
return defaultValue;
|
|
17
|
+
}
|
|
18
|
+
function isEnvFlagEnabled(key, defaultValue, env = process.env) {
|
|
19
|
+
return parseEnvFlag(env[key], defaultValue);
|
|
20
|
+
}
|
|
21
|
+
var TRUTHY, FALSY;
|
|
22
|
+
var init_env_flag = __esm(() => {
|
|
23
|
+
TRUTHY = new Set(["true", "1"]);
|
|
24
|
+
FALSY = new Set(["false", "0"]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export { parseEnvFlag, isEnvFlagEnabled, init_env_flag };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
contentSha256,
|
|
3
3
|
init_profile_sync
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-rpp0x4zy.js";
|
|
5
5
|
import {
|
|
6
6
|
getDb,
|
|
7
7
|
init_db,
|
|
8
8
|
isSqliteVecAvailable
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-zfbf3srj.js";
|
|
10
10
|
import {
|
|
11
11
|
__esm,
|
|
12
12
|
__export,
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
getEmbeddingProvider,
|
|
5
5
|
init_embedding,
|
|
6
6
|
serializeEmbedding
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-r6tpm37h.js";
|
|
8
8
|
import {
|
|
9
9
|
getDb,
|
|
10
10
|
init_db
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-zfbf3srj.js";
|
|
12
12
|
import {
|
|
13
13
|
init_secret_scrubber,
|
|
14
14
|
scrubSecrets
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IDENTITY_FIELD_BUDGETS,
|
|
3
|
+
init_identity_field_budget,
|
|
4
|
+
init_templates
|
|
5
|
+
} from "./cli-hkwfe3qj.js";
|
|
6
|
+
import {
|
|
7
|
+
init_resolver,
|
|
8
|
+
resolveTemplateAsync
|
|
9
|
+
} from "./cli-qes8ef67.js";
|
|
1
10
|
import {
|
|
2
11
|
MAX_PROFILE_FILE_LENGTH,
|
|
3
12
|
init_constants
|
|
@@ -14,6 +23,100 @@ import {
|
|
|
14
23
|
function contentSha256(content) {
|
|
15
24
|
return new Bun.CryptoHasher("sha256").update(content).digest("hex");
|
|
16
25
|
}
|
|
26
|
+
async function renderProfileSyncRejectionBanner(event) {
|
|
27
|
+
const data = event.data;
|
|
28
|
+
const field = data?.field;
|
|
29
|
+
const diskSize = data?.diskSize;
|
|
30
|
+
const dbSize = data?.dbSize;
|
|
31
|
+
const budget = data?.budget;
|
|
32
|
+
const delta = data?.delta;
|
|
33
|
+
if (typeof field !== "string" || !(field in PROFILE_FIELD_DETAILS) || typeof diskSize !== "number" || typeof dbSize !== "number" || typeof budget !== "number" || typeof delta !== "number") {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const details = PROFILE_FIELD_DETAILS[field];
|
|
37
|
+
const result = await resolveTemplateAsync("task.profile_sync_rejection", {
|
|
38
|
+
timestamp: event.createdAt,
|
|
39
|
+
field_label: details.label,
|
|
40
|
+
disk_size: diskSize,
|
|
41
|
+
db_size: dbSize,
|
|
42
|
+
budget,
|
|
43
|
+
delta: delta >= 0 ? `+${delta}` : String(delta),
|
|
44
|
+
event_id: event.id,
|
|
45
|
+
recovery_guidance: details.recoveryGuidance
|
|
46
|
+
});
|
|
47
|
+
return result.skipped ? null : result.text;
|
|
48
|
+
}
|
|
49
|
+
async function fetchProfileSyncRejectionBanner(config, fetchImpl = fetch, readFile = readFileIfExists) {
|
|
50
|
+
try {
|
|
51
|
+
const responses = await Promise.all(Object.keys(IDENTITY_FIELD_BUDGETS).map(async (field) => {
|
|
52
|
+
const fetchLatestEvent = async (event) => {
|
|
53
|
+
const query = new URLSearchParams({
|
|
54
|
+
event,
|
|
55
|
+
agentId: config.agentId,
|
|
56
|
+
dataField: field,
|
|
57
|
+
limit: "1"
|
|
58
|
+
});
|
|
59
|
+
const response = await fetchImpl(`${config.apiUrl}/api/events?${query}`, {
|
|
60
|
+
headers: {
|
|
61
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
62
|
+
"X-Agent-ID": config.agentId
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok)
|
|
66
|
+
return null;
|
|
67
|
+
const payload = await response.json();
|
|
68
|
+
return payload.events?.[0] ?? null;
|
|
69
|
+
};
|
|
70
|
+
const [rejection, reconciliation] = await Promise.all([
|
|
71
|
+
fetchLatestEvent("system.profile_sync_rejected"),
|
|
72
|
+
fetchLatestEvent("system.profile_sync_reconciled")
|
|
73
|
+
]);
|
|
74
|
+
return { rejection, reconciliation };
|
|
75
|
+
}));
|
|
76
|
+
const latestEvents = responses.flatMap(({ rejection, reconciliation }) => rejection ? [{ rejection, reconciliation }] : []);
|
|
77
|
+
if (latestEvents.length === 0)
|
|
78
|
+
return "";
|
|
79
|
+
let profile = null;
|
|
80
|
+
const profileResponse = await fetchImpl(`${config.apiUrl}/me`, {
|
|
81
|
+
headers: {
|
|
82
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
83
|
+
"X-Agent-ID": config.agentId
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (profileResponse.ok) {
|
|
87
|
+
profile = await profileResponse.json();
|
|
88
|
+
}
|
|
89
|
+
let disk = null;
|
|
90
|
+
if (config.claudeMdPath) {
|
|
91
|
+
disk = {
|
|
92
|
+
soulMd: await readFile(SOUL_MD_PATH),
|
|
93
|
+
identityMd: await readFile(IDENTITY_MD_PATH),
|
|
94
|
+
claudeMd: await readFile(config.claudeMdPath),
|
|
95
|
+
toolsMd: await readFile(TOOLS_MD_PATH)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const unresolved = latestEvents.flatMap(({ rejection, reconciliation }) => {
|
|
99
|
+
if (reconciliation && reconciliation.createdAt > rejection.createdAt)
|
|
100
|
+
return [];
|
|
101
|
+
const event = rejection;
|
|
102
|
+
const field = event.data?.field;
|
|
103
|
+
const rejectedDbHash = event.data?.dbHash;
|
|
104
|
+
const currentValue = typeof field === "string" ? profile?.[field] : undefined;
|
|
105
|
+
const diskValue = typeof field === "string" ? disk?.[field] : undefined;
|
|
106
|
+
if (typeof currentValue === "string" && diskValue === currentValue)
|
|
107
|
+
return [];
|
|
108
|
+
return !(typeof rejectedDbHash === "string" && typeof currentValue === "string" && contentSha256(currentValue) !== rejectedDbHash) ? [event] : [];
|
|
109
|
+
});
|
|
110
|
+
const banners = await Promise.all(unresolved.map(renderProfileSyncRejectionBanner));
|
|
111
|
+
return banners.filter((banner) => banner !== null).join("");
|
|
112
|
+
} catch {
|
|
113
|
+
return "";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function prependProfileSyncRejectionBanner(prompt, config, fetchImpl = fetch, readFile = readFileIfExists) {
|
|
117
|
+
const banner = await fetchProfileSyncRejectionBanner(config, fetchImpl, readFile);
|
|
118
|
+
return banner ? { prompt: banner + prompt, injected: true } : { prompt, injected: false };
|
|
119
|
+
}
|
|
17
120
|
async function writeIdentityBaselines(baselines) {
|
|
18
121
|
await Bun.write(IDENTITY_BASELINES_PATH, JSON.stringify(baselines));
|
|
19
122
|
}
|
|
@@ -47,6 +150,12 @@ function resolveClaudeMdPath(completedProviders) {
|
|
|
47
150
|
const anyNonClaude = completedProviders.some((p) => p !== "claude");
|
|
48
151
|
return anyNonClaude ? WORKSPACE_CLAUDE_MD_PATH : CLAUDE_MD_PATH;
|
|
49
152
|
}
|
|
153
|
+
function buildIndependentIdentityPayloads(updates, changeSource) {
|
|
154
|
+
return Object.entries(updates).map(([field, value]) => ({
|
|
155
|
+
label: `identity.${field}`,
|
|
156
|
+
body: { [field]: value, changeSource }
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
50
159
|
function extractSetupScriptContent(raw, agentId = "unknown") {
|
|
51
160
|
if (!raw.trim())
|
|
52
161
|
return null;
|
|
@@ -70,9 +179,7 @@ function buildIdentityPayload(files, baselines, agentId = "unknown") {
|
|
|
70
179
|
const updates = {};
|
|
71
180
|
if (files.soulMd !== undefined) {
|
|
72
181
|
const content = files.soulMd;
|
|
73
|
-
if (baselines?.soulMd && contentSha256(content) === baselines.soulMd) {} else if (content.
|
|
74
|
-
warnProfileFileTooLarge(agentId, "soulMd", content.length);
|
|
75
|
-
} else if (content.trim()) {
|
|
182
|
+
if (baselines?.soulMd && contentSha256(content) === baselines.soulMd) {} else if (content.trim()) {
|
|
76
183
|
if (content.length < IDENTITY_FILE_MIN_LENGTH) {
|
|
77
184
|
console.error(`[profile-sync] Skipping SOUL.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
|
|
78
185
|
} else {
|
|
@@ -82,9 +189,7 @@ function buildIdentityPayload(files, baselines, agentId = "unknown") {
|
|
|
82
189
|
}
|
|
83
190
|
if (files.identityMd !== undefined) {
|
|
84
191
|
const content = files.identityMd;
|
|
85
|
-
if (baselines?.identityMd && contentSha256(content) === baselines.identityMd) {} else if (content.
|
|
86
|
-
warnProfileFileTooLarge(agentId, "identityMd", content.length);
|
|
87
|
-
} else if (content.trim()) {
|
|
192
|
+
if (baselines?.identityMd && contentSha256(content) === baselines.identityMd) {} else if (content.trim()) {
|
|
88
193
|
if (content.length < IDENTITY_FILE_MIN_LENGTH) {
|
|
89
194
|
console.error(`[profile-sync] Skipping IDENTITY.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
|
|
90
195
|
} else {
|
|
@@ -94,9 +199,7 @@ function buildIdentityPayload(files, baselines, agentId = "unknown") {
|
|
|
94
199
|
}
|
|
95
200
|
if (files.toolsMd !== undefined) {
|
|
96
201
|
const content = files.toolsMd;
|
|
97
|
-
if (baselines?.toolsMd && contentSha256(content) === baselines.toolsMd) {} else if (content.
|
|
98
|
-
warnProfileFileTooLarge(agentId, "toolsMd", content.length);
|
|
99
|
-
} else if (content.trim()) {
|
|
202
|
+
if (baselines?.toolsMd && contentSha256(content) === baselines.toolsMd) {} else if (content.trim()) {
|
|
100
203
|
updates.toolsMd = content;
|
|
101
204
|
}
|
|
102
205
|
}
|
|
@@ -130,15 +233,11 @@ async function collectProfilePayloads(fields, changeSource, readFile = readFileI
|
|
|
130
233
|
toolsMd: await readFile(TOOLS_MD_PATH),
|
|
131
234
|
heartbeatMd: await readFile(HEARTBEAT_MD_PATH)
|
|
132
235
|
}, baselines, agentId);
|
|
133
|
-
|
|
134
|
-
payloads.push({ label: "identity", body: { ...updates, changeSource } });
|
|
135
|
-
}
|
|
236
|
+
payloads.push(...buildIndependentIdentityPayloads(updates, changeSource));
|
|
136
237
|
}
|
|
137
238
|
if (fields.includes("claude")) {
|
|
138
239
|
const raw = await readFile(claudeMdPath);
|
|
139
|
-
if (raw
|
|
140
|
-
warnProfileFileTooLarge(agentId, "claudeMd", raw.length);
|
|
141
|
-
} else if (raw?.trim()) {
|
|
240
|
+
if (raw?.trim()) {
|
|
142
241
|
if (baselines?.claudeMd && contentSha256(raw) === baselines.claudeMd) {} else {
|
|
143
242
|
payloads.push({ label: "claude", body: { claudeMd: raw, changeSource } });
|
|
144
243
|
}
|
|
@@ -187,11 +286,32 @@ async function syncProfileFilesToServer(opts) {
|
|
|
187
286
|
await postProfileUpdate(opts, payload);
|
|
188
287
|
}
|
|
189
288
|
}
|
|
190
|
-
var SOUL_MD_PATH = "/workspace/SOUL.md", IDENTITY_MD_PATH = "/workspace/IDENTITY.md", TOOLS_MD_PATH = "/workspace/TOOLS.md", HEARTBEAT_MD_PATH = "/workspace/HEARTBEAT.md", SETUP_SCRIPT_PATH = "/workspace/start-up.sh", IDENTITY_BASELINES_PATH = "/tmp/identity-baselines.json", CLAUDE_MD_PATH, WORKSPACE_CLAUDE_MD_PATH = "/workspace/CLAUDE.md", IDENTITY_FILE_MIN_LENGTH = 500, SETUP_MARKER_START = "# === Agent-managed setup (from DB) ===", SETUP_MARKER_END = "# === End agent-managed setup ===";
|
|
289
|
+
var SOUL_MD_PATH = "/workspace/SOUL.md", IDENTITY_MD_PATH = "/workspace/IDENTITY.md", TOOLS_MD_PATH = "/workspace/TOOLS.md", HEARTBEAT_MD_PATH = "/workspace/HEARTBEAT.md", SETUP_SCRIPT_PATH = "/workspace/start-up.sh", IDENTITY_BASELINES_PATH = "/tmp/identity-baselines.json", PROFILE_FIELD_DETAILS, CLAUDE_MD_PATH, WORKSPACE_CLAUDE_MD_PATH = "/workspace/CLAUDE.md", IDENTITY_FILE_MIN_LENGTH = 500, SETUP_MARKER_START = "# === Agent-managed setup (from DB) ===", SETUP_MARKER_END = "# === End agent-managed setup ===";
|
|
191
290
|
var init_profile_sync = __esm(() => {
|
|
291
|
+
init_resolver();
|
|
192
292
|
init_constants();
|
|
293
|
+
init_identity_field_budget();
|
|
193
294
|
init_secret_scrubber();
|
|
295
|
+
init_templates();
|
|
296
|
+
PROFILE_FIELD_DETAILS = {
|
|
297
|
+
soulMd: {
|
|
298
|
+
label: `soulMd (${SOUL_MD_PATH})`,
|
|
299
|
+
recoveryGuidance: `Inspect and shrink the live ${SOUL_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${SOUL_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
|
|
300
|
+
},
|
|
301
|
+
identityMd: {
|
|
302
|
+
label: `identityMd (${IDENTITY_MD_PATH})`,
|
|
303
|
+
recoveryGuidance: `Inspect and shrink the live ${IDENTITY_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${IDENTITY_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
|
|
304
|
+
},
|
|
305
|
+
claudeMd: {
|
|
306
|
+
label: "claudeMd (/workspace/CLAUDE.md for non-Claude harnesses; ~/.claude/CLAUDE.md for Claude)",
|
|
307
|
+
recoveryGuidance: "Inspect and shrink the live CLAUDE.md source first, moving durable tail content into memory. After a worker restart, non-Claude harnesses can use /workspace/CLAUDE.md.pre-boot-<timestamp>.bak as the fallback copy; Claude's native ~/.claude/CLAUDE.md source is not archived by that boot step."
|
|
308
|
+
},
|
|
309
|
+
toolsMd: {
|
|
310
|
+
label: `toolsMd (${TOOLS_MD_PATH})`,
|
|
311
|
+
recoveryGuidance: `Inspect and shrink the live ${TOOLS_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${TOOLS_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
|
|
312
|
+
}
|
|
313
|
+
};
|
|
194
314
|
CLAUDE_MD_PATH = `${process.env.HOME}/.claude/CLAUDE.md`;
|
|
195
315
|
});
|
|
196
316
|
|
|
197
|
-
export { contentSha256, writeIdentityBaselines, readIdentityBaselines, warnProfileFileTooLarge, writeProfileFileFromDb, resolveClaudeMdPath, syncProfileFilesToServer, init_profile_sync };
|
|
317
|
+
export { contentSha256, prependProfileSyncRejectionBanner, writeIdentityBaselines, readIdentityBaselines, warnProfileFileTooLarge, writeProfileFileFromDb, resolveClaudeMdPath, buildIndependentIdentityPayloads, syncProfileFilesToServer, init_profile_sync };
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
require_p_retry
|
|
11
11
|
} from "./cli-b0p7rfnd.js";
|
|
12
12
|
import {
|
|
13
|
+
getJsonSchemaToolParameters,
|
|
13
14
|
resolveJsonSchemaStrictSampling,
|
|
14
15
|
transformMessages
|
|
15
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-xmyqv00z.js";
|
|
16
17
|
import {
|
|
17
18
|
sanitizeSurrogates
|
|
18
19
|
} from "./cli-y2apkfe2.js";
|
|
@@ -25221,16 +25222,20 @@ function sanitizeForOpenApi(schema) {
|
|
|
25221
25222
|
}
|
|
25222
25223
|
return result;
|
|
25223
25224
|
}
|
|
25224
|
-
function convertTools(tools, useParameters = false) {
|
|
25225
|
+
function convertTools(tools, useParameters = false, supportsStrictMode = true) {
|
|
25225
25226
|
if (tools.length === 0)
|
|
25226
25227
|
return;
|
|
25227
25228
|
return [
|
|
25228
25229
|
{
|
|
25229
|
-
functionDeclarations: tools.map((tool) =>
|
|
25230
|
-
|
|
25231
|
-
|
|
25232
|
-
|
|
25233
|
-
|
|
25230
|
+
functionDeclarations: tools.map((tool) => {
|
|
25231
|
+
const strict = resolveJsonSchemaStrictSampling(tool, supportsStrictMode);
|
|
25232
|
+
const parameters = getJsonSchemaToolParameters(tool, strict);
|
|
25233
|
+
return {
|
|
25234
|
+
name: tool.name,
|
|
25235
|
+
description: tool.description,
|
|
25236
|
+
...useParameters ? { parameters: sanitizeForOpenApi(parameters) } : { parametersJsonSchema: parameters }
|
|
25237
|
+
};
|
|
25238
|
+
})
|
|
25234
25239
|
}
|
|
25235
25240
|
];
|
|
25236
25241
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
summarizeSession
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-5z2yhzvd.js";
|
|
4
4
|
import {
|
|
5
5
|
checkToolLoop,
|
|
6
6
|
clearToolHistory
|
|
@@ -11,29 +11,30 @@ import {
|
|
|
11
11
|
fetchRetrievalsForTask,
|
|
12
12
|
isLlmRaterEnabled,
|
|
13
13
|
postRatings
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-f8dre4bz.js";
|
|
15
15
|
import {
|
|
16
16
|
getApiKey
|
|
17
17
|
} from "./cli-f14fvzag.js";
|
|
18
18
|
import {
|
|
19
|
+
buildIndependentIdentityPayloads,
|
|
19
20
|
contentSha256,
|
|
20
21
|
init_profile_sync,
|
|
21
22
|
readIdentityBaselines,
|
|
22
23
|
warnProfileFileTooLarge
|
|
23
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-rpp0x4zy.js";
|
|
24
25
|
import {
|
|
25
26
|
MAX_PROFILE_FILE_LENGTH,
|
|
26
27
|
getMcpBaseUrl,
|
|
27
28
|
init_constants
|
|
28
29
|
} from "./cli-x23me2mg.js";
|
|
30
|
+
import {
|
|
31
|
+
init_package,
|
|
32
|
+
package_default
|
|
33
|
+
} from "./cli-9nfc2es8.js";
|
|
29
34
|
import {
|
|
30
35
|
init_secret_scrubber,
|
|
31
36
|
scrubSecrets
|
|
32
37
|
} from "./cli-4j2mrzag.js";
|
|
33
|
-
import {
|
|
34
|
-
init_package,
|
|
35
|
-
package_default
|
|
36
|
-
} from "./cli-ccf9vy7q.js";
|
|
37
38
|
|
|
38
39
|
// src/hooks/hook.ts
|
|
39
40
|
init_package();
|
|
@@ -57,6 +58,31 @@ function shouldShowRegistrationNudge(opts) {
|
|
|
57
58
|
return false;
|
|
58
59
|
return true;
|
|
59
60
|
}
|
|
61
|
+
async function postHookProfileUpdate({
|
|
62
|
+
url,
|
|
63
|
+
headers,
|
|
64
|
+
body,
|
|
65
|
+
label,
|
|
66
|
+
fetchImpl = fetch
|
|
67
|
+
}) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetchImpl(url, {
|
|
70
|
+
method: "PUT",
|
|
71
|
+
headers: {
|
|
72
|
+
...headers,
|
|
73
|
+
"Content-Type": "application/json"
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify(body)
|
|
76
|
+
});
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
const responseBody = await response.text();
|
|
79
|
+
console.error(scrubSecrets(`[hook] ${label} profile sync failed: HTTP ${response.status}${responseBody ? ` — ${responseBody}` : ""}`));
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
83
|
+
console.error(scrubSecrets(`[hook] ${label} profile sync errored: ${message}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
60
86
|
async function readTaskFile() {
|
|
61
87
|
const taskFilePath = process.env.TASK_FILE;
|
|
62
88
|
if (!taskFilePath) {
|
|
@@ -362,20 +388,12 @@ async function handleHook() {
|
|
|
362
388
|
const content = await file.text();
|
|
363
389
|
if (!content.trim())
|
|
364
390
|
return;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
method: "PUT",
|
|
372
|
-
headers: {
|
|
373
|
-
...mcpConfig.headers,
|
|
374
|
-
"Content-Type": "application/json"
|
|
375
|
-
},
|
|
376
|
-
body: JSON.stringify({ claudeMd: content, changeSource: "session_sync" })
|
|
377
|
-
});
|
|
378
|
-
} catch {}
|
|
391
|
+
await postHookProfileUpdate({
|
|
392
|
+
url: `${getBaseUrl()}/api/agents/${agentId}/profile`,
|
|
393
|
+
headers: mcpConfig.headers,
|
|
394
|
+
body: { claudeMd: content, changeSource: "session_sync" },
|
|
395
|
+
label: "claudeMd"
|
|
396
|
+
});
|
|
379
397
|
};
|
|
380
398
|
const IDENTITY_FILE_MIN_LENGTH = 500;
|
|
381
399
|
const syncIdentityFilesToServer = async (agentId, changeSource = "session_sync") => {
|
|
@@ -386,9 +404,7 @@ async function handleHook() {
|
|
|
386
404
|
const soulFile = Bun.file(SOUL_MD_PATH);
|
|
387
405
|
if (await soulFile.exists()) {
|
|
388
406
|
const content = await soulFile.text();
|
|
389
|
-
if (baselines?.soulMd && contentSha256(content) === baselines.soulMd) {} else if (content.
|
|
390
|
-
warnProfileFileTooLarge(agentId, "soulMd", content.length, "hook");
|
|
391
|
-
} else if (content.trim()) {
|
|
407
|
+
if (baselines?.soulMd && contentSha256(content) === baselines.soulMd) {} else if (content.trim()) {
|
|
392
408
|
if (content.length < IDENTITY_FILE_MIN_LENGTH) {
|
|
393
409
|
console.error(`[hook] Skipping SOUL.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
|
|
394
410
|
} else {
|
|
@@ -399,9 +415,7 @@ async function handleHook() {
|
|
|
399
415
|
const identityFile = Bun.file(IDENTITY_MD_PATH);
|
|
400
416
|
if (await identityFile.exists()) {
|
|
401
417
|
const content = await identityFile.text();
|
|
402
|
-
if (baselines?.identityMd && contentSha256(content) === baselines.identityMd) {} else if (content.
|
|
403
|
-
warnProfileFileTooLarge(agentId, "identityMd", content.length, "hook");
|
|
404
|
-
} else if (content.trim()) {
|
|
418
|
+
if (baselines?.identityMd && contentSha256(content) === baselines.identityMd) {} else if (content.trim()) {
|
|
405
419
|
if (content.length < IDENTITY_FILE_MIN_LENGTH) {
|
|
406
420
|
console.error(`[hook] Skipping IDENTITY.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
|
|
407
421
|
} else {
|
|
@@ -412,9 +426,7 @@ async function handleHook() {
|
|
|
412
426
|
const toolsMdFile = Bun.file(TOOLS_MD_PATH);
|
|
413
427
|
if (await toolsMdFile.exists()) {
|
|
414
428
|
const content = await toolsMdFile.text();
|
|
415
|
-
if (baselines?.toolsMd && contentSha256(content) === baselines.toolsMd) {} else if (content.
|
|
416
|
-
warnProfileFileTooLarge(agentId, "toolsMd", content.length, "hook");
|
|
417
|
-
} else if (content.trim()) {
|
|
429
|
+
if (baselines?.toolsMd && contentSha256(content) === baselines.toolsMd) {} else if (content.trim()) {
|
|
418
430
|
updates.toolsMd = content;
|
|
419
431
|
}
|
|
420
432
|
}
|
|
@@ -429,16 +441,14 @@ async function handleHook() {
|
|
|
429
441
|
}
|
|
430
442
|
if (Object.keys(updates).length === 0)
|
|
431
443
|
return;
|
|
432
|
-
|
|
433
|
-
await
|
|
434
|
-
|
|
435
|
-
headers:
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
},
|
|
439
|
-
body: JSON.stringify({ ...updates, changeSource })
|
|
444
|
+
for (const payload of buildIndependentIdentityPayloads(updates, changeSource)) {
|
|
445
|
+
await postHookProfileUpdate({
|
|
446
|
+
url: `${getBaseUrl()}/api/agents/${agentId}/profile`,
|
|
447
|
+
headers: mcpConfig.headers,
|
|
448
|
+
body: payload.body,
|
|
449
|
+
label: payload.label
|
|
440
450
|
});
|
|
441
|
-
}
|
|
451
|
+
}
|
|
442
452
|
};
|
|
443
453
|
const syncSetupScriptToServer = async (agentId, changeSource = "session_sync") => {
|
|
444
454
|
if (!mcpConfig)
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
getAgentWorkingOnThread,
|
|
4
4
|
getAllAgents,
|
|
5
5
|
init_db
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-zfbf3srj.js";
|
|
7
7
|
import {
|
|
8
8
|
init_env_flag,
|
|
9
9
|
isEnvFlagEnabled
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-qys3rhhz.js";
|
|
11
11
|
|
|
12
12
|
// src/slack/router.ts
|
|
13
13
|
init_db();
|
|
@@ -1,4 +1,112 @@
|
|
|
1
1
|
// node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js
|
|
2
|
+
class UnsupportedStrictJsonSchemaError extends Error {
|
|
3
|
+
}
|
|
4
|
+
var UNSUPPORTED_STRICT_SCHEMA_KEYS = [
|
|
5
|
+
"$ref",
|
|
6
|
+
"$defs",
|
|
7
|
+
"definitions",
|
|
8
|
+
"allOf",
|
|
9
|
+
"oneOf",
|
|
10
|
+
"patternProperties",
|
|
11
|
+
"dependentSchemas",
|
|
12
|
+
"dependencies",
|
|
13
|
+
"unevaluatedProperties",
|
|
14
|
+
"propertyNames",
|
|
15
|
+
"contains",
|
|
16
|
+
"prefixItems",
|
|
17
|
+
"not",
|
|
18
|
+
"if",
|
|
19
|
+
"then",
|
|
20
|
+
"else"
|
|
21
|
+
];
|
|
22
|
+
function isJsonSchemaObject(value) {
|
|
23
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
function isStructuredSchema(schema) {
|
|
26
|
+
if (!isJsonSchemaObject(schema))
|
|
27
|
+
return false;
|
|
28
|
+
const types = typeof schema.type === "string" ? [schema.type] : Array.isArray(schema.type) ? schema.type : [];
|
|
29
|
+
return types.includes("object") || types.includes("array") || schema.properties !== undefined || schema.items !== undefined;
|
|
30
|
+
}
|
|
31
|
+
function schemaAllowsNull(schema) {
|
|
32
|
+
if (!isJsonSchemaObject(schema))
|
|
33
|
+
return false;
|
|
34
|
+
if (schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null"))
|
|
35
|
+
return true;
|
|
36
|
+
if (schema.const === null || Array.isArray(schema.enum) && schema.enum.includes(null))
|
|
37
|
+
return true;
|
|
38
|
+
return Array.isArray(schema.anyOf) && schema.anyOf.some((variant) => schemaAllowsNull(variant));
|
|
39
|
+
}
|
|
40
|
+
function makeJsonSchemaNodeStrict(schema) {
|
|
41
|
+
if (!isJsonSchemaObject(schema)) {
|
|
42
|
+
throw new UnsupportedStrictJsonSchemaError("boolean schemas are unsupported");
|
|
43
|
+
}
|
|
44
|
+
for (const key of UNSUPPORTED_STRICT_SCHEMA_KEYS) {
|
|
45
|
+
if (schema[key] !== undefined) {
|
|
46
|
+
throw new UnsupportedStrictJsonSchemaError(`${key} schemas are unsupported`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (schema.anyOf !== undefined) {
|
|
50
|
+
if (!Array.isArray(schema.anyOf) || schema.anyOf.length === 0) {
|
|
51
|
+
throw new UnsupportedStrictJsonSchemaError("anyOf must contain at least one schema");
|
|
52
|
+
}
|
|
53
|
+
for (const variant of schema.anyOf) {
|
|
54
|
+
if (isStructuredSchema(variant)) {
|
|
55
|
+
throw new UnsupportedStrictJsonSchemaError("object and array unions are unsupported");
|
|
56
|
+
}
|
|
57
|
+
makeJsonSchemaNodeStrict(variant);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (schema.items !== undefined) {
|
|
61
|
+
if (Array.isArray(schema.items)) {
|
|
62
|
+
throw new UnsupportedStrictJsonSchemaError("tuple schemas are unsupported");
|
|
63
|
+
}
|
|
64
|
+
makeJsonSchemaNodeStrict(schema.items);
|
|
65
|
+
}
|
|
66
|
+
const isObjectSchema = schema.type === "object";
|
|
67
|
+
if (schema.properties !== undefined && !isObjectSchema) {
|
|
68
|
+
throw new UnsupportedStrictJsonSchemaError("properties require type object");
|
|
69
|
+
}
|
|
70
|
+
if (!isObjectSchema)
|
|
71
|
+
return;
|
|
72
|
+
if (schema.additionalProperties !== undefined && schema.additionalProperties !== false) {
|
|
73
|
+
throw new UnsupportedStrictJsonSchemaError("schema-valued or true additionalProperties is unsupported");
|
|
74
|
+
}
|
|
75
|
+
if (schema.properties !== undefined && !isJsonSchemaObject(schema.properties)) {
|
|
76
|
+
throw new UnsupportedStrictJsonSchemaError("object properties must be a schema map");
|
|
77
|
+
}
|
|
78
|
+
if (schema.required !== undefined && (!Array.isArray(schema.required) || schema.required.some((key) => typeof key !== "string"))) {
|
|
79
|
+
throw new UnsupportedStrictJsonSchemaError("object required must be a string array");
|
|
80
|
+
}
|
|
81
|
+
const properties = schema.properties ?? {};
|
|
82
|
+
const propertyNames = Object.keys(properties);
|
|
83
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
84
|
+
if ([...required].some((key) => !propertyNames.includes(key))) {
|
|
85
|
+
throw new UnsupportedStrictJsonSchemaError("required contains an unknown property");
|
|
86
|
+
}
|
|
87
|
+
for (const [key, property] of Object.entries(properties)) {
|
|
88
|
+
makeJsonSchemaNodeStrict(property);
|
|
89
|
+
if (!required.has(key) && !schemaAllowsNull(property)) {
|
|
90
|
+
properties[key] = { anyOf: [property, { type: "null" }] };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
schema.required = propertyNames;
|
|
94
|
+
schema.additionalProperties = false;
|
|
95
|
+
}
|
|
96
|
+
function makeStrictJsonSchema(schema) {
|
|
97
|
+
const cloned = structuredClone(schema);
|
|
98
|
+
if (!isJsonSchemaObject(cloned)) {
|
|
99
|
+
throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
100
|
+
}
|
|
101
|
+
makeJsonSchemaNodeStrict(cloned);
|
|
102
|
+
if (cloned.type !== "object") {
|
|
103
|
+
throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
104
|
+
}
|
|
105
|
+
return cloned;
|
|
106
|
+
}
|
|
107
|
+
function getJsonSchemaToolParameters(tool, strict) {
|
|
108
|
+
return strict === true ? makeStrictJsonSchema(tool.parameters) : tool.parameters;
|
|
109
|
+
}
|
|
2
110
|
function getGrammarToolInput(toolName, arguments_, inputProperty) {
|
|
3
111
|
const input = arguments_[inputProperty];
|
|
4
112
|
if (typeof input !== "string") {
|
|
@@ -50,11 +158,19 @@ function inferGrammarInputProperty(tool) {
|
|
|
50
158
|
}
|
|
51
159
|
function resolveJsonSchemaStrictSampling(tool, supportsStrictMode) {
|
|
52
160
|
const config = tool.constrainedSampling;
|
|
53
|
-
if (!config || config.type !== "json_schema")
|
|
161
|
+
if (!config || config.type !== "json_schema")
|
|
54
162
|
return;
|
|
55
|
-
}
|
|
56
163
|
if (supportsStrictMode) {
|
|
57
|
-
|
|
164
|
+
try {
|
|
165
|
+
makeStrictJsonSchema(tool.parameters);
|
|
166
|
+
return true;
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (!(error instanceof UnsupportedStrictJsonSchemaError))
|
|
169
|
+
throw error;
|
|
170
|
+
if (config.strict !== "require")
|
|
171
|
+
return;
|
|
172
|
+
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but ${error.message}.`);
|
|
173
|
+
}
|
|
58
174
|
}
|
|
59
175
|
if (config.strict === "require") {
|
|
60
176
|
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but strict tools are unsupported.`);
|
|
@@ -413,4 +529,4 @@ function transformMessages(messages, model, normalizeToolCallId) {
|
|
|
413
529
|
return result;
|
|
414
530
|
}
|
|
415
531
|
|
|
416
|
-
export { getGrammarToolInput, appendGrammarToolInputJsonDelta, resolveJsonSchemaStrictSampling, resolveGrammarConstrainedSampling, createGrammarToolInputProperties, clampMaxTokensToContext, buildBaseOptions, MIN_ANSWER_TOKENS, clampReasoning, adjustMaxTokensForThinking, transformMessages };
|
|
532
|
+
export { getJsonSchemaToolParameters, getGrammarToolInput, appendGrammarToolInputJsonDelta, resolveJsonSchemaStrictSampling, resolveGrammarConstrainedSampling, createGrammarToolInputProperties, clampMaxTokensToContext, buildBaseOptions, MIN_ANSWER_TOKENS, clampReasoning, adjustMaxTokensForThinking, transformMessages };
|