pi-background-tasks 2.6.0 → 2.6.2
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/PUBLISHING.md +1 -1
- package/README.md +2 -2
- package/TESTING.md +3 -1
- package/TEST_PLAN.md +4 -3
- package/dist/extensions/anthropic-attribution-child.js +5 -1
- package/dist/extensions/anthropic-attribution-child.js.map +1 -1
- package/dist/extensions/anthropic-attribution.js +7 -12
- package/dist/extensions/anthropic-attribution.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/core/anthropic-attribution.js +14 -8
- package/dist/src/core/anthropic-attribution.js.map +1 -1
- package/docs/INDEX.md +1 -1
- package/docs/commands/claude-cache.md +1 -1
- package/docs/manifest.json +5 -5
- package/docs/operations/releasing.md +1 -1
- package/docs/operations/testing.md +1 -1
- package/docs/operations/troubleshooting.md +2 -0
- package/docs/reference/runtime-contracts.md +3 -3
- package/docs/subsystems/anthropic-attribution.md +4 -4
- package/docs/subsystems/delegation.md +1 -1
- package/docs/subsystems/docs-freshness-gate.md +1 -1
- package/docs/subsystems/host-ui-and-telemetry.md +3 -1
- package/extensions/anthropic-attribution-child.ts +8 -1
- package/extensions/anthropic-attribution.ts +7 -16
- package/package.json +2 -1
- package/src/core/anthropic-attribution.ts +21 -7
package/docs/INDEX.md
CHANGED
|
@@ -133,7 +133,7 @@ Generated navigation for every package-local documentation page. This index inte
|
|
|
133
133
|
| command | `bg-clear` | `command:bg-clear` | `always` | yes | `src/extension.ts:793` |
|
|
134
134
|
| command | `bg-tasks` | `command:bg-tasks` | `always` | yes | `src/extension.ts:785` |
|
|
135
135
|
| command | `bg-update` | `command:bg-update` | `always` | yes | `src/extension.ts:801` |
|
|
136
|
-
| command | `claude-cache` | `command:claude-cache` | `feature:attribution` | yes | `src/core/anthropic-attribution.ts:
|
|
136
|
+
| command | `claude-cache` | `command:claude-cache` | `feature:attribution` | yes | `src/core/anthropic-attribution.ts:3220` |
|
|
137
137
|
| command | `fusion` | `command:fusion` | `feature:fusion` | yes | `src/fusion-extension.ts:1083` |
|
|
138
138
|
| command | `fusion-models` | `command:fusion-models` | `feature:fusion` | yes | `src/fusion-extension.ts:1123` |
|
|
139
139
|
| command | `jobs` | `command:jobs` | `always` | yes | `src/extension.ts:850` |
|
|
@@ -12,7 +12,7 @@ covers_sources: []
|
|
|
12
12
|
<!-- pi-docs:begin name="command-contract-claude-cache" generator="scripts/docs/generate.mjs" -->
|
|
13
13
|
| Command | Availability | Default | Description | Provenance |
|
|
14
14
|
| --- | --- | --- | --- | --- |
|
|
15
|
-
| `/claude-cache` | `feature:attribution` | yes | Show or set Claude cache retention for this session (short, long, default) | `src/core/anthropic-attribution.ts:
|
|
15
|
+
| `/claude-cache` | `feature:attribution` | yes | Show or set Claude cache retention for this session (short, long, default) | `src/core/anthropic-attribution.ts:3220` |
|
|
16
16
|
<!-- pi-docs:end name="command-contract-claude-cache" -->
|
|
17
17
|
|
|
18
18
|
Show or change the Anthropic cache-retention preference for the current session. Under the initialized-host contract, the command is registered only when `PI_BG_FEATURES` includes the ambient `attribution` capability (enabled by default); disabling that capability removes the command together with the parent provider/hooks. Its generated default availability is not a pre-bind availability guarantee: bare SDK sessions and empty/mode-only reloads require the explicit binding described in [Anthropic attribution](../subsystems/anthropic-attribution.md#initialized-host-sdk-contract-and-blocker).
|
package/docs/manifest.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"state": "stale-authored-prose"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
|
-
"authored_body_sha256": "sha256:
|
|
28
|
+
"authored_body_sha256": "sha256:1668305b87b152b6fc98ba3f7bcf029269d4f042a4b39192232a3cc472fdc2ae",
|
|
29
29
|
"covers_sources": [
|
|
30
30
|
"extensions/anthropic-attribution-child.ts",
|
|
31
31
|
"extensions/anthropic-attribution.ts",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"state": "stale-authored-prose"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
|
-
"authored_body_sha256": "sha256:
|
|
82
|
+
"authored_body_sha256": "sha256:d1e5920202ddc1368fa94148ad96906784937084d6ef5a72f1153f8dc3a4374e",
|
|
83
83
|
"covers_sources": [
|
|
84
84
|
"extensions/delegate-child.ts",
|
|
85
85
|
"src/core/delegate/artifacts.ts",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"state": "stale-authored-prose"
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
|
-
"authored_body_sha256": "sha256:
|
|
138
|
+
"authored_body_sha256": "sha256:e1fdd8fbce4cb918fb8f361b4c13b1f78fadd455a5a18b22836a6f0b466f4119",
|
|
139
139
|
"covers_sources": [
|
|
140
140
|
"extensions/background-tasks.ts",
|
|
141
141
|
"src/core/config.ts",
|
|
@@ -909,7 +909,7 @@
|
|
|
909
909
|
"image": "https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png",
|
|
910
910
|
"name": "pi-background-tasks",
|
|
911
911
|
"type": "module",
|
|
912
|
-
"version": "2.6.
|
|
912
|
+
"version": "2.6.2"
|
|
913
913
|
},
|
|
914
914
|
"public_surface_ids": [
|
|
915
915
|
"command:bg",
|
|
@@ -990,7 +990,7 @@
|
|
|
990
990
|
"id": "command:claude-cache",
|
|
991
991
|
"kind": "command",
|
|
992
992
|
"name": "claude-cache",
|
|
993
|
-
"source": "src/core/anthropic-attribution.ts:
|
|
993
|
+
"source": "src/core/anthropic-attribution.ts:3220"
|
|
994
994
|
},
|
|
995
995
|
{
|
|
996
996
|
"availability": "feature:fusion",
|
|
@@ -57,7 +57,7 @@ Use `npm pack --dry-run --json` output as the payload source of truth. Verify at
|
|
|
57
57
|
- authoritative `extensions/` and runtime `src/` sources remain included for public source/API compatibility;
|
|
58
58
|
- `docs/`, `README.md`, `TESTING.md`, `TEST_PLAN.md`, `PUBLISHING.md`, `BACKGROUND-TASKS-INSTRUCTIONS.md`, `THIRD_PARTY_NOTICES.md`, root `logo.png`, and `LICENSE` are included per current `package.json.files`;
|
|
59
59
|
- tests, scripts, node_modules, local `.pi/` artifacts, generated evidence not meant for runtime, and nested tarballs are excluded;
|
|
60
|
-
- TypeBox
|
|
60
|
+
- TypeBox and `@earendil-works/pi-ai` remain Pi-provided peers and no private/nested runtime copies are bundled;
|
|
61
61
|
- production dependencies use registry versions only; no exotic URL/git/file subdependency is shipped;
|
|
62
62
|
- docs/assets/gateway/logo inclusion matches `package.json.files` exactly.
|
|
63
63
|
|
|
@@ -72,7 +72,7 @@ Here, **cold** means a fresh process and empty JavaScript/Jiti module cache. It
|
|
|
72
72
|
|
|
73
73
|
The benchmark requires an explicit `--runtime source|compiled` choice. Published package entrypoints select the compiled JavaScript distribution, while source mode remains an authoritative development control. Process-only startup no longer statically imports delegate/Fusion facades, dock UI, the attribution transport, or attested execution; enabled registrations still load their lightweight facade before the extension factory resolves. Neither mode supports a native-Windows or vendor compiled-Bun timing claim without separate runs.
|
|
74
74
|
|
|
75
|
-
The package gate separately walks literal deferred imports, verifies every source target, builds its compiled counterpart, and requires the complete `dist/` closure in the tarball. A packed-copy regression
|
|
75
|
+
The package gate separately walks literal deferred imports, verifies every source target, builds its compiled counterpart, and requires the complete `dist/` closure in the tarball. A packed-copy regression installs only the real production Turndown/Domino closure, proves all Pi SDK packages and TypeBox are absent beneath the package, and loads both compiled entrypoints through Pi's real SDK loader with default capabilities. Before damage injection it invokes `bg_delegate`, `bg_run_pi_attested`, `fusion_reason`, the task manager, and the Fusion selector; each must pass module loading and reach its expected post-import semantic boundary. It then removes one delegate producer module: startup and immediate inventory still work, the first producer invocation fails with the bounded module-specific error, and no delegate artifact is created. A source-graph guard also pins the host import on every internal dynamic-import issuer. This distinguishes supported package entrypoint traversal from unsupported direct Node imports of private `dist/src/**` chunks, without borrowing development dependencies or weakening the real payload-closure check.
|
|
76
76
|
|
|
77
77
|
Lazy lifecycle SDK coverage deliberately blocks Fusion cleanup while asserting the shared synchronous fence has already closed delegate, result, command/UI, and both Fusion lanes. A real `AgentSession.reload()` control lets production delegate preparation finish a complete artifact tree before returning, then proves the unregistered transaction is rolled back with no starter or residual run bytes. A separate claim race proves shutdown cannot consume Fusion usage without a successful retrieval, and a registered-task control proves rollback never deletes registry-owned artifacts.
|
|
78
78
|
|
|
@@ -42,6 +42,8 @@ Start from the symptom, verify the source-owned doc, then apply the remediation.
|
|
|
42
42
|
| Fusion research URL rejected | Source URL is not declared/public http(s), has credentials, resolves to blocked address class, or redirects unsafely | Provide declared public source URLs with purpose; targeted fetch is not search. |
|
|
43
43
|
| `/fusion-models` rejects in non-TUI mode | Selector requires interactive UI | Use an interactive Pi TUI session to edit config; headless path should fail loudly. |
|
|
44
44
|
| `/bg-update` shows no update | Offline/opt-out/current-version/registry failure path | Check `PI_OFFLINE`, `PI_BG_DISABLE_UPDATE_CHECK`, `PI_BG_REGISTRY_URL`; update check is one-shot and non-blocking. |
|
|
45
|
+
| `Cannot find package '@earendil-works/pi-ai' imported from .../dist/src/core/anthropic-attribution.js` during Pi startup | A stale compiled attribution gateway crossed its lazy native-import boundary before resolving Pi's host alias | Update the package to a fixed build. Do not install or bundle a private Pi SDK copy; the gateway must resolve and inject the host-owned adapter. Start temporarily with `PI_BG_FEATURES=process pi` or `pi -ne`. |
|
|
46
|
+
| A custom extension directly imports `pi-background-tasks/dist/src/**` and reports a missing Pi SDK package | Private compiled implementation chunks were imported through Node instead of the package's Pi entrypoints | Load the package through `package.json.pi.extensions` or its documented public surfaces. If an actual package command/tool fails, report that invocation and full stack; do not install duplicate Pi SDK packages to make a private-chunk probe pass. |
|
|
45
47
|
| TypeBox/compat failure | Installed package resolved a private/nested TypeBox or used removed APIs | Keep TypeBox as Pi-provided peer and verify installed payload. See `docs/operations/releasing.md`. |
|
|
46
48
|
|
|
47
49
|
Detailed references: EventBus API (`docs/api/eventbus-v1.md`), context budgeting (`docs/concepts/context-projection-and-budgeting.md`), launch/durability (`docs/subsystems/child-launch-durability-and-safety.md`), runtime registry (`docs/reference/runtime-contracts.md`), testing (`docs/operations/testing.md`), releasing (`docs/operations/releasing.md`).
|
|
@@ -63,7 +63,7 @@ This generated registry lists production environment-variable references, runtim
|
|
|
63
63
|
| `path` | read | `src/core/common.ts:963` |
|
|
64
64
|
| `Path` | read | `src/core/common.ts:963` |
|
|
65
65
|
| `PATH` | read | `src/core/common.ts:1017`<br>`src/core/common.ts:963`<br>`src/core/pi-launch.ts:425` |
|
|
66
|
-
| `PI_ANTHROPIC_ACCOUNT_CONFIG_PATH` | read | `src/core/anthropic-attribution.ts:
|
|
66
|
+
| `PI_ANTHROPIC_ACCOUNT_CONFIG_PATH` | read | `src/core/anthropic-attribution.ts:896` |
|
|
67
67
|
| `PI_API_BASE_URL` | remove | `src/core/attested-pi-run.ts:248`<br>`src/core/fusion/pi-child.ts:100` |
|
|
68
68
|
| `PI_API_KEY` | remove | `src/core/attested-pi-run.ts:248`<br>`src/core/fusion/pi-child.ts:100` |
|
|
69
69
|
| `PI_AUTH_FILE` | remove | `src/core/attested-pi-run.ts:248`<br>`src/core/fusion/pi-child.ts:100` |
|
|
@@ -82,7 +82,7 @@ This generated registry lists production environment-variable references, runtim
|
|
|
82
82
|
| `PI_BG_REGISTRY_URL` | read | `src/extension.ts:665` |
|
|
83
83
|
| `PI_BG_SHELL` | read | `src/core/common.ts:1042` |
|
|
84
84
|
| `PI_BG_SHELL_PATH` | read | `src/core/common.ts:1043` |
|
|
85
|
-
| `PI_CACHE_RETENTION` | read, write | `src/core/anthropic-attribution.ts:
|
|
85
|
+
| `PI_CACHE_RETENTION` | read, write | `src/core/anthropic-attribution.ts:661`<br>`src/core/anthropic-attribution.ts:672`<br>`src/core/fusion/claude-cache.ts:57`<br>`src/core/fusion/pi-child.ts:273`<br>`src/core/fusion/pi-child.ts:274` |
|
|
86
86
|
| `PI_FUSION_CANDIDATE_OUTPUT_RECOVERY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1879`<br>`src/fusion-child-extension.ts:599` |
|
|
87
87
|
| `PI_FUSION_RESEARCH_ENABLED` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1902`<br>`src/fusion-child-extension.ts:608` |
|
|
88
88
|
| `PI_FUSION_SOURCE_POLICY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1903`<br>`src/fusion-child-extension.ts:555` |
|
|
@@ -95,7 +95,7 @@ This generated registry lists production environment-variable references, runtim
|
|
|
95
95
|
| `PI_SESSION_FILE` | remove | `src/core/delegate/launch.ts:330`<br>`src/core/fusion/pi-child.ts:100` |
|
|
96
96
|
| `PI_SESSION_ID` | remove | `src/core/delegate/launch.ts:330`<br>`src/core/fusion/pi-child.ts:100` |
|
|
97
97
|
| `PI_SKIP_VERSION_CHECK` | write | `src/core/delegate/launch.ts:352`<br>`src/core/fusion/pi-child.ts:272` |
|
|
98
|
-
| `PIPELINE_ANTHROPIC_ATTRIBUTION_AUDIT_PATH` | read | `src/core/anthropic-attribution.ts:
|
|
98
|
+
| `PIPELINE_ANTHROPIC_ATTRIBUTION_AUDIT_PATH` | read | `src/core/anthropic-attribution.ts:1173` |
|
|
99
99
|
| `SHELL` | read | `src/core/common.ts:1102` |
|
|
100
100
|
| `SystemRoot` | read | `src/core/windows-taskkill.ts:96` |
|
|
101
101
|
| `WINDIR` | read | `src/core/windows-taskkill.ts:101` |
|
|
@@ -13,9 +13,9 @@ This subsystem owns the package-wide Anthropic subscription attribution provider
|
|
|
13
13
|
|
|
14
14
|
## Global package behavior
|
|
15
15
|
|
|
16
|
-
`package.json.pi.extensions` loads the compiled `dist/extensions/anthropic-attribution.js` entrypoint before the compiled background-task entrypoint; `extensions/anthropic-attribution.ts` remains its authoritative source. The light entrypoint parses the complete shared configuration
|
|
16
|
+
`package.json.pi.extensions` loads the compiled `dist/extensions/anthropic-attribution.js` entrypoint before the compiled background-task entrypoint; `extensions/anthropic-attribution.ts` remains its authoritative source. The light entrypoint statically resolves the host-owned `anthropicMessagesApi` through Pi's alias-aware extension loader, parses the complete shared configuration, and then dynamically loads the attribution transport with that adapter injected. The deferred core has no runtime import of a Pi host package, so a native dynamic import cannot look for a private `@earendil-works/pi-ai` beside a production-only package installation. With the default `attribution` capability, the wrapper activates the accepted implementation from `session_start`, after Pi has bound its public provider runtime; without that token the transport module is not imported and no parent provider, attribution lifecycle hooks, duplicate-owner responder, or `/claude-cache` command is registered. Invalid feature or dock configuration fails before ambient activation.
|
|
17
17
|
|
|
18
|
-
Before activation, the wrapper snapshots the effective provider plus the public legacy/native registration through `ctx.modelRegistry`. The accepted factory's provider call is then immediate rather than queued. A thrown application failure occurs before its command, hooks, or claim responder are published. A successful installation is owned only after a new current legacy-config object and changed effective provider are observed; that exact config object is the instance token. On shutdown the wrapper acts only while that token is still current. A later legacy or native owner is left untouched. Otherwise it restores the prior native registration directly, clears the package layer with the captured effective provider before reapplying a prior legacy config, or—when there was no prior dynamic registration—uses public unregister only after the exact token/later-owner checks to restore dynamic-registration absence
|
|
18
|
+
Before activation, the wrapper snapshots the effective provider plus the public legacy/native registration through `ctx.modelRegistry`. The accepted factory's provider call is then immediate rather than queued. A thrown application failure occurs before its command, hooks, or claim responder are published. A successful installation is owned only after a new current legacy-config object and changed effective provider are observed; that exact config object is the instance token. On shutdown the wrapper acts only while that token is still current. A later legacy or native owner is left untouched. Otherwise it restores the prior native registration directly, clears the package layer with the captured effective provider before reapplying a prior legacy config, or—when there was no prior dynamic registration—uses public unregister only after the exact token/later-owner checks to restore dynamic-registration absence. Postconditions verify the complete public registration state and a usable effective provider; they do not require a stale built-in object identity because Pi may legitimately refresh its host-owned provider while the package overlay is active. The wrapper never blindly deletes another owner's provider and never reads private host state. A subsequent real reload with attribution disabled therefore restores the host's prior public registration state. When enabled, the transport remains provider-gated: non-Anthropic sessions and payloads are unchanged.
|
|
19
19
|
|
|
20
20
|
## Initialized-host SDK contract and blocker
|
|
21
21
|
|
|
@@ -36,7 +36,7 @@ For Anthropic sessions it registers the package-owned `anthropic` provider trans
|
|
|
36
36
|
|
|
37
37
|
The extension reads `userID` and `oauthAccount.accountUuid` without writing account configuration. The loader precedence is: an explicit `loadClaudeAttributionAccount(path)` argument (the programmatic/test seam), then `PI_ANTHROPIC_ACCOUNT_CONFIG_PATH`, then `~/.claude.json`. An explicit selection must be a non-empty absolute file path. The selected file must be readable JSON with both non-empty fields; failures identify the selected path and field without fabricating account data. The package does not infer a Claude config-directory convention. Package-owned children inherit the path variable unchanged without copying account contents into their environment.
|
|
38
38
|
|
|
39
|
-
The registered provider can be reached with a non-`anthropic` model that uses the `anthropic-messages` API. That path passes the host-owned model, context, and options by identity to the matching host SDK's supported `anthropicMessagesApi().streamSimple` implementation and returns its event stream directly. The package neither validates against a frozen transcript shape nor reconstructs events/results: legacy top-level `Context` and normalized system-message `TranscriptContext` contracts remain owned by the host version, including shared live partial identity, optional fields, tool metadata, usage, callbacks, and terminal error settlement. It does not receive account, identity, cache, endpoint, or header rewriting and does not dispatch through the registered API adapter again. Missing/malformed account data on the target route, unsupported model policy, malformed payload/cache controls, and non-OAuth target transport fail loudly.
|
|
39
|
+
The registered provider can be reached with a non-`anthropic` model that uses the `anthropic-messages` API. That path passes the host-owned model, context, and options by identity to the gateway-injected matching host SDK's supported `anthropicMessagesApi().streamSimple` implementation and returns its event stream directly. A missing injected adapter fails loudly rather than resolving or reconstructing a private fallback. The package neither validates against a frozen transcript shape nor reconstructs events/results: legacy top-level `Context` and normalized system-message `TranscriptContext` contracts remain owned by the host version, including shared live partial identity, optional fields, tool metadata, usage, callbacks, and terminal error settlement. It does not receive account, identity, cache, endpoint, or header rewriting and does not dispatch through the registered API adapter again. Missing/malformed account data on the target route, unsupported model policy, malformed payload/cache controls, and non-OAuth target transport fail loudly.
|
|
40
40
|
|
|
41
41
|
## Cross-provider history and cache lineage
|
|
42
42
|
|
|
@@ -68,7 +68,7 @@ Ambient discovery and the parent capability flag are both insufficient for child
|
|
|
68
68
|
- Anthropic delegate children, before the delegate guard;
|
|
69
69
|
- Anthropic attested Pi children.
|
|
70
70
|
|
|
71
|
-
The child entrypoint directly
|
|
71
|
+
The child entrypoint resolves and injects the same host-owned adapter before directly invoking the accepted implementation, and deliberately does not consult `PI_BG_FEATURES`. Non-Anthropic child argv does not resolve or add it. Missing package extension bytes fail before child creation; no route substitution or sanitizer fallback is attempted. Delegate and Fusion keep attribution before their guard/governor, and attested Anthropic argv adds the same entrypoint before the prompt.
|
|
72
72
|
|
|
73
73
|
Arbitrary shell commands started through `bg_run` are not rewritten. An Anthropic child `pi` launched this way may keep normal extension discovery enabled when ambient attribution is enabled. If the command deliberately uses `--no-extensions`, it must explicitly load this package's always-on `extensions/anthropic-attribution-child.ts` with `-e`/`--extension`; otherwise attribution and sanitization are bypassed and the launch is unsupported. The package does not parse or override arbitrary shell authority.
|
|
74
74
|
|
|
@@ -39,7 +39,7 @@ Enabled schemas, descriptions, argument preparation, renderers, and tool registr
|
|
|
39
39
|
|
|
40
40
|
Each loader is activation-local and single-flight: simultaneous cold calls await one module import but continue as independent runs. Its states are `unloaded`, `loading`, `loaded`, `failed`, and `closed`. An import failure is wrapped with a bounded module-specific diagnostic and remains sticky for that activation. The entrypoint constructs one activation-local synchronous close fence and explicitly gives it to every enabled core, Fusion, delegate, and result lane. Its first shutdown handler closes every loader, advances Fusion generation, aborts Fusion controllers, and aborts delegate preparation before any later handler can await cleanup. A module arriving after closure is discarded before its operation can create an artifact, task, or child or touch stale host APIs. Reload constructs a new facade and may retry; the closed instance is never reopened, and no process-global cache stores `pi` or host context.
|
|
41
41
|
|
|
42
|
-
The main entrypoint dynamically imports the lightweight delegate/result facade only when delegate or Fusion is enabled. Process-only startup therefore imports neither advanced facade nor verifier/producer code. Published Pi entrypoints execute precompiled JavaScript from `dist/`; authoritative TypeScript remains shipped for source/API compatibility and development tests.
|
|
42
|
+
The main entrypoint dynamically imports the lightweight delegate/result facade only when delegate or Fusion is enabled. Process-only startup therefore imports neither advanced facade nor verifier/producer code. Published Pi entrypoints execute precompiled JavaScript from `dist/`; authoritative TypeScript remains shipped for source/API compatibility and development tests. The compiled `dist/src/**` files are private chunks reached through those Pi entrypoints, not standalone Node entrypoints. Packed-package tests exercise successful delegate/result first use without any package-local Pi SDK peer.
|
|
43
43
|
|
|
44
44
|
## Seed and context policy
|
|
45
45
|
|
|
@@ -16,7 +16,7 @@ The finite grammar recognizes only a top-level immutable binding returned by the
|
|
|
16
16
|
Every registration-owning function, imported registrar, and supported activation callback is checked as a whole, including parameter declarations and initializers. Destructured registration bindings, computed or property registration methods on unknown hosts, default-parameter host aliases, initializer calls/throws/control flow, and unmodeled body returns or throws are rejected. The sole early-return form is the structurally validated synchronous Anthropic duplicate-owner guard: the exact production claim channel, exact schema field/value and closed probe shape, one local empty acknowledgement array, one adjacent direct claim emit with the exact acknowledgement append, and the positive-length bare return. A local pre-probe claim listener is not accepted. Returns inside command/tool/event handlers that own no registrations remain unrelated and legal. Extracted surfaces carry a normalized availability expression and source-derived default status through the manifest, INDEX/read gate, README facts, and generated surface contracts.
|
|
17
17
|
|
|
18
18
|
<!-- pi-docs:begin name="docs-freshness-gate" generator="scripts/docs/generate.mjs" -->
|
|
19
|
-
- Canonical package version: `2.6.
|
|
19
|
+
- Canonical package version: `2.6.2`
|
|
20
20
|
- Governed markdown docs: 42
|
|
21
21
|
- Public surfaces extracted: 32
|
|
22
22
|
- Public surfaces available by default: 31
|
|
@@ -13,7 +13,9 @@ This subsystem owns the extension entrypoint, command/tool registration, footer
|
|
|
13
13
|
|
|
14
14
|
## Entrypoint and registration
|
|
15
15
|
|
|
16
|
-
The published `dist/extensions/background-tasks.js` entrypoint is compiled from `extensions/background-tasks.ts`, which re-exports the authoritative `src/extension.ts`.
|
|
16
|
+
The published `dist/extensions/background-tasks.js` entrypoint is compiled from `extensions/background-tasks.ts`, which re-exports the authoritative `src/extension.ts`. Only the ordered paths in `package.json.pi.extensions` and the package-owned child extension paths are supported extension roots. Files under `dist/src/**` are private compiled implementation chunks, not standalone Node entrypoints. Importing one directly from an unrelated natively loaded extension bypasses Pi's Jiti host-module aliases and is unsupported. The packed-package gate instead exercises every public lazy lane through the real package entrypoint with no package-local Pi SDK or TypeBox installation.
|
|
17
|
+
|
|
18
|
+
Before creating the registry or registering a surface, the extension strictly parses the shared capability/shortcut configuration. It dynamically imports delegate/Fusion facade registration only for enabled capabilities; the dock component is imported only when an interactive manager is opened. `process` is mandatory and registers:
|
|
17
19
|
|
|
18
20
|
- commands: `/bg`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update`, `/jobs`, `/logs`, `/kill`;
|
|
19
21
|
- tools: `bg_run`, `bg_status`, `bg_logs`, `bg_kill`;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { anthropicMessagesApi } from '@earendil-works/pi-ai/compat';
|
|
2
|
+
import spawnAnthropicAttribution, {
|
|
3
|
+
type PiExtensionHost,
|
|
4
|
+
} from '../src/core/anthropic-attribution.js';
|
|
5
|
+
|
|
1
6
|
// Always-on safety entrypoint for package-owned isolated Anthropic children.
|
|
2
7
|
// Ambient parent capability selection must never disable this extension.
|
|
3
|
-
export
|
|
8
|
+
export default function childAnthropicAttribution(pi: PiExtensionHost): void {
|
|
9
|
+
spawnAnthropicAttribution(pi, { hostAnthropicMessagesApi: anthropicMessagesApi });
|
|
10
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Provider } from '@earendil-works/pi-ai';
|
|
2
|
+
import { anthropicMessagesApi } from '@earendil-works/pi-ai/compat';
|
|
2
3
|
import type { ModelRegistry } from '@earendil-works/pi-coding-agent';
|
|
3
4
|
import type { PiContextLike, PiExtensionHost } from '../src/core/anthropic-attribution.js';
|
|
4
5
|
import { parseBackgroundTasksConfig } from '../src/core/config.js';
|
|
@@ -104,7 +105,9 @@ function restoreProviderInstallation(installation: ProviderInstallation): void {
|
|
|
104
105
|
} else {
|
|
105
106
|
// The exact package token and absence of a later native owner were proven above.
|
|
106
107
|
// Public unregister is therefore owner-conditional here: it removes only this
|
|
107
|
-
// still-current package layer and restores
|
|
108
|
+
// still-current package layer and restores dynamic-registration absence. The host
|
|
109
|
+
// may legitimately refresh its built-in provider while our overlay is installed,
|
|
110
|
+
// so that host-owned effective object is not required to retain stale identity.
|
|
108
111
|
registry.unregisterProvider(ANTHROPIC_PROVIDER);
|
|
109
112
|
}
|
|
110
113
|
|
|
@@ -121,25 +124,13 @@ function restoreProviderInstallation(installation: ProviderInstallation): void {
|
|
|
121
124
|
(before.native !== undefined
|
|
122
125
|
? restoredNative === before.native
|
|
123
126
|
: restoredNative === undefined);
|
|
124
|
-
const streamIdentityRestored =
|
|
125
|
-
before.legacy !== undefined
|
|
126
|
-
? restoredConfig?.streamSimple === before.legacy.streamSimple
|
|
127
|
-
: restoredEffective?.streamSimple === before.effective.streamSimple;
|
|
128
|
-
const effectiveIdentityRestored =
|
|
129
|
-
before.legacy !== undefined || restoredEffective === before.effective;
|
|
130
127
|
const registeredIdRestored =
|
|
131
128
|
before.legacy !== undefined || before.native !== undefined
|
|
132
129
|
? restoredIds.includes(ANTHROPIC_PROVIDER)
|
|
133
130
|
: !restoredIds.includes(ANTHROPIC_PROVIDER);
|
|
134
|
-
if (
|
|
135
|
-
!registrationRestored ||
|
|
136
|
-
restoredEffective === undefined ||
|
|
137
|
-
!streamIdentityRestored ||
|
|
138
|
-
!effectiveIdentityRestored ||
|
|
139
|
-
!registeredIdRestored
|
|
140
|
-
) {
|
|
131
|
+
if (!registrationRestored || restoredEffective === undefined || !registeredIdRestored) {
|
|
141
132
|
throw new Error(
|
|
142
|
-
'pi_anthropic_attribution_restore_failed: the preexisting
|
|
133
|
+
'pi_anthropic_attribution_restore_failed: the preexisting public provider registration state was not restored',
|
|
143
134
|
);
|
|
144
135
|
}
|
|
145
136
|
}
|
|
@@ -154,7 +145,7 @@ export default async function ambientAnthropicAttribution(pi: PiExtensionHost):
|
|
|
154
145
|
pi.on('session_start', (_event, context) => {
|
|
155
146
|
const registry = (context as AmbientAttributionContext).modelRegistry;
|
|
156
147
|
const before = captureProviderSnapshot(registry);
|
|
157
|
-
spawnAnthropicAttribution(pi);
|
|
148
|
+
spawnAnthropicAttribution(pi, { hostAnthropicMessagesApi: anthropicMessagesApi });
|
|
158
149
|
installation = confirmProviderInstallation(registry, before) ?? installation;
|
|
159
150
|
});
|
|
160
151
|
pi.on('session_shutdown', () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-background-tasks",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.2",
|
|
4
4
|
"description": "Pi extension for durable background shell tasks, read-only delegated agents, local attested Pi runs, and fixed-purpose Fusion workflows through child Pi processes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
]
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
|
+
"@earendil-works/pi-ai": "*",
|
|
91
92
|
"@earendil-works/pi-coding-agent": "^0.81.1 || ^0.82.1 || ^0.83.0 || ^0.84.0",
|
|
92
93
|
"@earendil-works/pi-tui": "^0.81.1 || ^0.82.1 || ^0.83.0 || ^0.84.0",
|
|
93
94
|
"typebox": "*"
|
|
@@ -2,7 +2,6 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { appendFileSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { isAbsolute, join } from 'node:path';
|
|
5
|
-
import { anthropicMessagesApi } from '@earendil-works/pi-ai/compat';
|
|
6
5
|
import type {
|
|
7
6
|
AssistantMessageEventStream as HostAssistantMessageEventStream,
|
|
8
7
|
Context as HostContext,
|
|
@@ -466,8 +465,12 @@ export interface PiSimpleStreamOptions {
|
|
|
466
465
|
) => Promise<void> | void;
|
|
467
466
|
}
|
|
468
467
|
|
|
468
|
+
export type HostAnthropicMessagesApiFactory =
|
|
469
|
+
typeof import('@earendil-works/pi-ai/compat').anthropicMessagesApi;
|
|
470
|
+
|
|
469
471
|
export interface AnthropicTransportDependencies {
|
|
470
472
|
readonly loadAccount?: () => ClaudeAttributionAccount;
|
|
473
|
+
readonly hostAnthropicMessagesApi?: HostAnthropicMessagesApiFactory;
|
|
471
474
|
}
|
|
472
475
|
|
|
473
476
|
export interface AssistantMessageLike {
|
|
@@ -2683,12 +2686,23 @@ function forwardToBuiltInAnthropic(
|
|
|
2683
2686
|
model: PiModelLike,
|
|
2684
2687
|
context: PiStreamContext,
|
|
2685
2688
|
options: PiSimpleStreamOptions | undefined,
|
|
2689
|
+
dependencies: AnthropicTransportDependencies,
|
|
2686
2690
|
): AssistantMessageEventStreamLike {
|
|
2687
|
-
//
|
|
2688
|
-
//
|
|
2689
|
-
//
|
|
2690
|
-
//
|
|
2691
|
-
const
|
|
2691
|
+
// The compiled gateway resolves this host-owned adapter through Pi's alias-aware
|
|
2692
|
+
// extension loader and injects it across the lazy native-import boundary. Keeping
|
|
2693
|
+
// the deferred core free of runtime Pi package imports prevents Node from trying to
|
|
2694
|
+
// resolve a private @earendil-works/pi-ai installation beside a managed package.
|
|
2695
|
+
const hostAnthropicMessagesApi = dependencies.hostAnthropicMessagesApi;
|
|
2696
|
+
if (hostAnthropicMessagesApi === undefined) {
|
|
2697
|
+
throw new Error(
|
|
2698
|
+
"pi_anthropic_attribution_host_adapter_missing: the extension gateway did not inject Pi's anthropic-messages adapter",
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2702
|
+
// The host owns both its legacy Context or normalized TranscriptContext input and
|
|
2703
|
+
// the complete stream/event/result shape. These intersections only mark that
|
|
2704
|
+
// host-owned boundary; no request, callback, event, or result is reconstructed.
|
|
2705
|
+
const delegated = hostAnthropicMessagesApi().streamSimple(
|
|
2692
2706
|
model as HostForwardingModel,
|
|
2693
2707
|
context as HostForwardingContext,
|
|
2694
2708
|
options as HostForwardingOptions | undefined,
|
|
@@ -2703,7 +2717,7 @@ export function streamAnthropicViaBetaMessages(
|
|
|
2703
2717
|
dependencies: AnthropicTransportDependencies = {},
|
|
2704
2718
|
): AssistantMessageEventStreamLike {
|
|
2705
2719
|
if (model.provider !== 'anthropic') {
|
|
2706
|
-
return forwardToBuiltInAnthropic(model, context, options);
|
|
2720
|
+
return forwardToBuiltInAnthropic(model, context, options, dependencies);
|
|
2707
2721
|
}
|
|
2708
2722
|
|
|
2709
2723
|
const stream = createAssistantMessageEventStream();
|