@senpiper/sp-agent 0.1.10 → 0.1.11
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/INSTALL.md +36 -24
- package/README.md +13 -13
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/distribution.d.ts +2 -2
- package/dist/distribution.d.ts.map +1 -1
- package/dist/distribution.js +1 -1
- package/dist/distribution.js.map +1 -1
- package/dist/extension-identity.generated.d.ts +3 -3
- package/dist/extension-identity.generated.d.ts.map +1 -1
- package/dist/extension-identity.generated.js +3 -3
- package/dist/extension-identity.generated.js.map +1 -1
- package/dist/install-sp.sh +9 -9
- package/dist/release-manager.d.ts.map +1 -1
- package/dist/release-manager.js +2 -2
- package/dist/release-manager.js.map +1 -1
- package/dist/runtime-cli.d.ts.map +1 -1
- package/dist/runtime-cli.js +4 -4
- package/dist/runtime-cli.js.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +5 -5
- package/dist/sdk.js.map +1 -1
- package/dist/session-manager.d.ts +1 -1
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +15 -15
- package/dist/session-manager.js.map +1 -1
- package/dist/sp-web.d.ts.map +1 -1
- package/dist/sp-web.js +2 -2
- package/dist/sp-web.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/node_modules/@senpiper/pi-coding-agent/dist/bundle/chunks/{chunk-LUSUF4ZH.js → chunk-VVKE4QZJ.js} +1 -1
- package/node_modules/@senpiper/pi-coding-agent/dist/bundle/cli.js +1 -1
- package/node_modules/@senpiper/pi-coding-agent/dist/bundle/index.js +1 -1
- package/node_modules/@senpiper/pi-coding-agent/dist/bundle/rpc-entry.js +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@senpiper/pi-coding-agent/package.json +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/CHANGELOG.md +17 -0
- package/node_modules/@senpiper/sp-agent-extensions/CONCURRENT_SESSIONS.md +9 -9
- package/node_modules/@senpiper/sp-agent-extensions/TERMINAL_WEB_BRIDGE.md +28 -9
- package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.js +5 -5
- package/node_modules/@senpiper/sp-agent-extensions/dist/cli-commands.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.d.ts +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.js +18 -18
- package/node_modules/@senpiper/sp-agent-extensions/dist/gateway.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/index.d.ts +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/index.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/index.js +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/index.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.js +9 -9
- package/node_modules/@senpiper/sp-agent-extensions/dist/login-command.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.d.ts +27 -0
- package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.js +270 -28
- package/node_modules/@senpiper/sp-agent-extensions/dist/sp-web-launcher.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.js +12 -19
- package/node_modules/@senpiper/sp-agent-extensions/dist/startup-header.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.d.ts +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.js +11 -9
- package/node_modules/@senpiper/sp-agent-extensions/dist/terminal-web-bridge.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.d.ts.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.js +36 -10
- package/node_modules/@senpiper/sp-agent-extensions/dist/web-command.js.map +1 -1
- package/node_modules/@senpiper/sp-agent-extensions/package.json +3 -2
- package/package.json +7 -6
package/INSTALL.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# Install
|
|
1
|
+
# Install Senpiper Workbench
|
|
2
2
|
|
|
3
|
-
This guide targets `@senpiper/sp-agent@0.1.7` and newer, which include
|
|
3
|
+
This guide targets `@senpiper/sp-agent@0.1.7` and newer, which include the web workspace.
|
|
4
4
|
|
|
5
|
-
Gateway: **https://sp-api.staging.senpiper.com/**
|
|
5
|
+
Senpiper Gateway: **https://sp-api.staging.senpiper.com/**
|
|
6
6
|
|
|
7
7
|
## Requirements
|
|
8
8
|
|
|
9
9
|
- Node.js **22.19.0 or newer**, with npm. Node.js 24 LTS is recommended.
|
|
10
|
-
-
|
|
10
|
+
- A Senpiper Gateway API key supplied by your administrator.
|
|
11
11
|
- A terminal and a web browser.
|
|
12
12
|
|
|
13
13
|
The workspace terminal uses a native PTY. Linux source builds require Python 3,
|
|
@@ -22,8 +22,8 @@ npm install --global @senpiper/sp-agent
|
|
|
22
22
|
|
|
23
23
|
One package installs both commands:
|
|
24
24
|
|
|
25
|
-
- `sp`: the terminal
|
|
26
|
-
- `sp-web`: the
|
|
25
|
+
- `sp`: the terminal application.
|
|
26
|
+
- `sp-web`: the web workspace server.
|
|
27
27
|
|
|
28
28
|
Check the installation:
|
|
29
29
|
|
|
@@ -48,16 +48,16 @@ npm install --global --allow-scripts=node-pty @senpiper/sp-agent
|
|
|
48
48
|
Without that approval, the applications can install while the workspace
|
|
49
49
|
terminal remains unavailable. Do not use `--ignore-scripts` if you need the PTY.
|
|
50
50
|
|
|
51
|
-
## 2. Connect to
|
|
51
|
+
## 2. Connect to Senpiper Gateway
|
|
52
52
|
|
|
53
|
-
Start
|
|
53
|
+
Start Senpiper Workbench from your project directory:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
56
|
cd /path/to/your/project
|
|
57
57
|
sp
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
Inside
|
|
60
|
+
Inside Senpiper Workbench, enter:
|
|
61
61
|
|
|
62
62
|
```text
|
|
63
63
|
/login https://sp-api.staging.senpiper.com/
|
|
@@ -66,10 +66,10 @@ Inside SP, enter:
|
|
|
66
66
|
Paste your gateway API key into the **masked API-key prompt**. Do not put the
|
|
67
67
|
key in a chat message, README, or shell command.
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Senpiper Workbench adds `/v1` to the supplied gateway URL, retrieves the available models,
|
|
70
70
|
and selects the first model.
|
|
71
71
|
|
|
72
|
-
Use `/model` in
|
|
72
|
+
Use `/model` in Senpiper Workbench to choose another available model. To inspect the model
|
|
73
73
|
catalog from a separate terminal:
|
|
74
74
|
|
|
75
75
|
```bash
|
|
@@ -82,20 +82,32 @@ For CLI-only setup, the equivalent command is:
|
|
|
82
82
|
sp login --gateway-url https://sp-api.staging.senpiper.com/
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
That CLI prompt is not masked. Prefer `/login` inside
|
|
85
|
+
That CLI prompt is not masked. Prefer `/login` inside Senpiper Workbench when entering a key.
|
|
86
86
|
|
|
87
|
-
## 3. Open
|
|
87
|
+
## 3. Open the web workspace
|
|
88
88
|
|
|
89
|
-
Interactive
|
|
89
|
+
Interactive Senpiper Workbench starts the web sidecar automatically. Open:
|
|
90
90
|
|
|
91
91
|
**http://127.0.0.1:30141**
|
|
92
92
|
|
|
93
|
-
Keep
|
|
94
|
-
connects to
|
|
93
|
+
Keep a Senpiper Workbench instance running to send prompts and manage live sessions. The web workspace
|
|
94
|
+
connects to Senpiper Workbench; it does not create a second writer for the same history file.
|
|
95
95
|
|
|
96
96
|
The workspace includes chat, native questions, files, Git diffs, and a terminal.
|
|
97
97
|
Commits and permanent thread deletion require confirmation.
|
|
98
98
|
|
|
99
|
+
Inside the terminal application:
|
|
100
|
+
|
|
101
|
+
- `/web` or `/web on` starts the web UI if needed and opens it in your browser.
|
|
102
|
+
- `/web off` stops the managed web server for this profile. Terminal agent
|
|
103
|
+
sessions and Senpiper Gateway keep running.
|
|
104
|
+
|
|
105
|
+
Stopping is temporary: `/web` starts it again, and the next interactive `sp`
|
|
106
|
+
launch can start it automatically. The server is shared by terminals using the
|
|
107
|
+
same profile, so stopping it disconnects their browsers too. Any workspace
|
|
108
|
+
shells running inside the web server may end; save work before stopping.
|
|
109
|
+
For a server you started manually with `sp-web`, use Ctrl+C in its terminal.
|
|
110
|
+
|
|
99
111
|
### Manual web startup
|
|
100
112
|
|
|
101
113
|
If you want to start the server yourself, disable automatic startup first:
|
|
@@ -120,17 +132,17 @@ Open `http://127.0.0.1:30142` yourself.
|
|
|
120
132
|
|
|
121
133
|
## Configuration and credentials
|
|
122
134
|
|
|
123
|
-
|
|
135
|
+
Senpiper Workbench stores its configuration and history under:
|
|
124
136
|
|
|
125
137
|
```text
|
|
126
138
|
~/.sp/agent/
|
|
127
139
|
```
|
|
128
140
|
|
|
129
141
|
Use `SP_CODING_AGENT_DIR` to select another profile. Set it consistently for
|
|
130
|
-
|
|
142
|
+
Senpiper Workbench and any manually started web workspace process.
|
|
131
143
|
|
|
132
|
-
The gateway key stays on the machine running
|
|
133
|
-
paste that key into
|
|
144
|
+
The gateway key stays on the machine running Senpiper Workbench. Browser users do not need to
|
|
145
|
+
paste that key into the web workspace. If web authentication is enabled with
|
|
134
146
|
`SP_WEB_PASSWORD`, use username **`sp`** and the configured web password.
|
|
135
147
|
The web password and the gateway API key are different credentials.
|
|
136
148
|
|
|
@@ -147,7 +159,7 @@ Update both applications together:
|
|
|
147
159
|
npm install --global @senpiper/sp-agent@latest
|
|
148
160
|
```
|
|
149
161
|
|
|
150
|
-
Use the npm 12 script-approval flag above when applicable. Restart
|
|
162
|
+
Use the npm 12 script-approval flag above when applicable. Restart Senpiper Workbench and its
|
|
151
163
|
web sidecar after updating, then refresh the browser. Existing processes do
|
|
152
164
|
not load replacement code automatically.
|
|
153
165
|
|
|
@@ -166,9 +178,9 @@ directory unless you intend to delete its credentials, settings, and history.
|
|
|
166
178
|
| --- | --- |
|
|
167
179
|
| `sp` or `sp-web` is not found | Open a new terminal and ensure your Node version manager's global npm bin directory is on `PATH`. |
|
|
168
180
|
| npm reports `EACCES` | Use a Node version manager or a user-writable npm prefix instead of a system-owned global installation. |
|
|
169
|
-
| `sp` is older than `0.1.7` | You have a release from before bundled
|
|
181
|
+
| `sp` is older than `0.1.7` | You have a release from before the bundled web workspace. Check that the new release is available in your npm registry. |
|
|
170
182
|
| Login returns `401` or `403` | Ask your administrator to verify the gateway API key and access permissions, then repeat `/login`. |
|
|
171
183
|
| No gateway models appear | Check gateway connectivity and repeat `/login` to synchronize the catalog. |
|
|
172
|
-
|
|
|
173
|
-
| Port `30141` is already in use | Open the existing
|
|
184
|
+
| The web workspace has no live session | Start `sp` in the project and confirm both processes use the same Senpiper Workbench profile. |
|
|
185
|
+
| Port `30141` is already in use | Open the existing web workspace, or choose another port for a manually started server. |
|
|
174
186
|
| Workspace terminal is unavailable | Check build tools and npm install-script approval for `node-pty`. |
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @senpiper/sp-agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Senpiper Workbench is Senpiper's Pi-based coding agent and web interface. This package includes the `sp` terminal application and the web workspace for the same sessions. It uses `~/.sp/agent` and routes model traffic through Senpiper Gateway (`sp-gateway`).
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
Requires Node.js 22.19 or newer.
|
|
8
8
|
|
|
9
9
|
See [the installation guide](INSTALL.md) for setup with
|
|
10
|
-
`https://sp-api.staging.senpiper.com/`, gateway login, and
|
|
10
|
+
`https://sp-api.staging.senpiper.com/`, gateway login, and the web workspace.
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
npm install --global @senpiper/sp-agent
|
|
@@ -17,13 +17,13 @@ sp
|
|
|
17
17
|
One installation provides both commands:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
sp # Start the terminal agent and its
|
|
21
|
-
sp-web # Start
|
|
20
|
+
sp # Start the terminal agent and its web sidecar
|
|
21
|
+
sp-web # Start the web workspace directly
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
The web workspace connects to running terminal sessions. Senpiper Workbench owns the agents and their history files; the web UI does not create a competing writer. Run `sp-web --help` for browser, address, port, and authentication options.
|
|
25
25
|
|
|
26
|
-
The package bundles the
|
|
26
|
+
The package bundles the Senpiper Workbench runtime and required extensions, and installs the exact `@senpiper/sp-web` dependency automatically. You do not need a separate web installation.
|
|
27
27
|
|
|
28
28
|
The workspace terminal uses `node-pty`. If its installer cannot use a prebuilt binary for your platform, npm compiles it locally. Linux source builds need Python 3, `make`, and a C/C++ compiler. Do not disable install scripts if you need the workspace terminal.
|
|
29
29
|
|
|
@@ -35,13 +35,13 @@ npm install --global --allow-scripts=node-pty @senpiper/sp-agent
|
|
|
35
35
|
|
|
36
36
|
The ordinary install still provides both applications, but a blocked native build can leave the workspace terminal unavailable.
|
|
37
37
|
|
|
38
|
-
Set `SP_WEB_DISABLE=1` to run
|
|
38
|
+
Set `SP_WEB_DISABLE=1` to run Senpiper Workbench without automatically starting the web sidecar. This does not uninstall the web workspace.
|
|
39
39
|
|
|
40
40
|
## Publishing
|
|
41
41
|
|
|
42
|
-
Build
|
|
42
|
+
Build the web workspace in a disposable copy of its repository, not a checkout running a development server. Pack the production build with `npm pack --ignore-scripts`.
|
|
43
43
|
|
|
44
|
-
Set the intended source versions before building. Pass the web tarball and its build lockfile to the
|
|
44
|
+
Set the intended source versions before building. Pass the web tarball and its build lockfile to the Senpiper Workbench release command. The dry run validates the web artifact, builds the Senpiper Workbench tarball, and checks a clean global installation without publishing:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
node scripts/publish-sp-packages.mjs --dry-run \
|
|
@@ -51,7 +51,7 @@ node scripts/publish-sp-packages.mjs --dry-run \
|
|
|
51
51
|
--output /absolute/path/release-artifacts
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
Copy the exact validated web tarball into that output directory alongside the
|
|
54
|
+
Copy the exact validated web tarball into that output directory alongside the Senpiper Workbench tarball. Keep exactly one tarball for each package there. Log in with an npm account that has write access to the `@senpiper` scope, then publish from an interactive terminal:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
npm run login:sp:npm
|
|
@@ -60,7 +60,7 @@ node scripts/publish-sp-npm-artifacts.mjs /absolute/path/release-artifacts --che
|
|
|
60
60
|
node scripts/publish-sp-npm-artifacts.mjs /absolute/path/release-artifacts
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
The artifact publisher checks registry hashes, publishes
|
|
63
|
+
The artifact publisher checks registry hashes, publishes the web workspace first and then the agent, and verifies each published hash. Complete npm's interactive 2FA prompt when requested. `--check` checks artifacts and registry state without publishing. If interrupted, rerun with the same artifacts; matching published versions are verified and skipped. Do not rebuild between attempts. The private runtime and extension packages remain bundled and do not need separate public releases.
|
|
64
64
|
|
|
65
65
|
The private `packages/sp-web-contract` workspace only records the required web version for source development. It is not the web application and is never used as the release artifact.
|
|
66
66
|
|
|
@@ -68,7 +68,7 @@ The supported programmatic entry point is `@senpiper/sp-agent/sdk`. It does not
|
|
|
68
68
|
|
|
69
69
|
## Concurrent web sessions
|
|
70
70
|
|
|
71
|
-
Interactive
|
|
71
|
+
Interactive Senpiper Workbench supplies an instance-owned session manager to its required bridge extension. Web `create_session {cwd}` and `resume_session {sessionFile}` return `{sessionId}` for an independently running session. Select its existing-format discovery descriptor to send commands. Terminal replacement and browser disconnection leave other sessions running.
|
|
72
72
|
|
|
73
73
|
SDK hosts can use the same verified factory:
|
|
74
74
|
|
|
@@ -88,7 +88,7 @@ try {
|
|
|
88
88
|
|
|
89
89
|
## Third-party notices
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Senpiper Workbench includes Pi code under the MIT license below. The web workspace's upstream license and T3 attribution are included in the installed `@senpiper/sp-web` package as `LICENSE` and `THIRD_PARTY_NOTICES.md`. Other dependencies retain their own licenses.
|
|
92
92
|
|
|
93
93
|
```text
|
|
94
94
|
MIT License
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { configureSpEnvironment } from \"./environment.ts\";\nimport { handleSpReleaseCommand } from \"./release-manager.ts\";\nimport { runSpRuntime } from \"./runtime-cli.ts\";\nimport { SP_AGENT_VERSION } from \"./version.ts\";\n\nfunction printHelp() {\n\tconsole.log(`
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { configureSpEnvironment } from \"./environment.ts\";\nimport { handleSpReleaseCommand } from \"./release-manager.ts\";\nimport { runSpRuntime } from \"./runtime-cli.ts\";\nimport { SP_AGENT_VERSION } from \"./version.ts\";\n\nfunction printHelp() {\n\tconsole.log(`Senpiper Workbench ${SP_AGENT_VERSION}\n\nUsage:\n sp Start the interactive terminal\n sp -p <prompt> Run a one-shot prompt\n sp --mode json|rpc Select a machine-readable mode\n sp --list-models List canonical Senpiper Gateway models\n sp login|logout Manage Senpiper Gateway credentials\n sp update|rollback|repair Manage the active verified release\n sp --help Show this help\n sp-web Start the Senpiper Workbench web workspace\n\nConfiguration: ~/.sp/agent (override with SP_CODING_AGENT_DIR)`);\n}\n\nasync function run() {\n\tconfigureSpEnvironment();\n\tprocess.title = \"sp\";\n\tconst args = process.argv.slice(2);\n\tif (args.length === 1 && (args[0] === \"--version\" || args[0] === \"-v\")) {\n\t\tconsole.log(SP_AGENT_VERSION);\n\t\treturn;\n\t}\n\tif (args.length === 1 && (args[0] === \"--help\" || args[0] === \"-h\")) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (await handleSpReleaseCommand(args)) return;\n\tawait runSpRuntime(args);\n}\n\nrun().catch((error) => {\n\tconsole.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n\tprocess.exitCode = 1;\n});\n"]}
|
package/dist/cli.js
CHANGED
|
@@ -4,17 +4,17 @@ import { handleSpReleaseCommand } from "./release-manager.js";
|
|
|
4
4
|
import { runSpRuntime } from "./runtime-cli.js";
|
|
5
5
|
import { SP_AGENT_VERSION } from "./version.js";
|
|
6
6
|
function printHelp() {
|
|
7
|
-
console.log(`
|
|
7
|
+
console.log(`Senpiper Workbench ${SP_AGENT_VERSION}
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
10
|
sp Start the interactive terminal
|
|
11
11
|
sp -p <prompt> Run a one-shot prompt
|
|
12
12
|
sp --mode json|rpc Select a machine-readable mode
|
|
13
|
-
sp --list-models List canonical
|
|
14
|
-
sp login|logout Manage
|
|
13
|
+
sp --list-models List canonical Senpiper Gateway models
|
|
14
|
+
sp login|logout Manage Senpiper Gateway credentials
|
|
15
15
|
sp update|rollback|repair Manage the active verified release
|
|
16
16
|
sp --help Show this help
|
|
17
|
-
sp-web Start the
|
|
17
|
+
sp-web Start the Senpiper Workbench web workspace
|
|
18
18
|
|
|
19
19
|
Configuration: ~/.sp/agent (override with SP_CODING_AGENT_DIR)`);
|
|
20
20
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,SAAS,SAAS,GAAG;IACpB,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,SAAS,SAAS,GAAG;IACpB,OAAO,CAAC,GAAG,CAAC,sBAAsB,gBAAgB;;;;;;;;;;;;+DAYY,CAAC,CAAC;AAAA,CAChE;AAED,KAAK,UAAU,GAAG,GAAG;IACpB,sBAAsB,EAAE,CAAC;IACzB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO;IACR,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACrE,SAAS,EAAE,CAAC;QACZ,OAAO;IACR,CAAC;IACD,IAAI,MAAM,sBAAsB,CAAC,IAAI,CAAC;QAAE,OAAO;IAC/C,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;AAAA,CACzB;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;IACtB,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AAAA,CACrB,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { configureSpEnvironment } from \"./environment.ts\";\nimport { handleSpReleaseCommand } from \"./release-manager.ts\";\nimport { runSpRuntime } from \"./runtime-cli.ts\";\nimport { SP_AGENT_VERSION } from \"./version.ts\";\n\nfunction printHelp() {\n\tconsole.log(`Senpiper Workbench ${SP_AGENT_VERSION}\n\nUsage:\n sp Start the interactive terminal\n sp -p <prompt> Run a one-shot prompt\n sp --mode json|rpc Select a machine-readable mode\n sp --list-models List canonical Senpiper Gateway models\n sp login|logout Manage Senpiper Gateway credentials\n sp update|rollback|repair Manage the active verified release\n sp --help Show this help\n sp-web Start the Senpiper Workbench web workspace\n\nConfiguration: ~/.sp/agent (override with SP_CODING_AGENT_DIR)`);\n}\n\nasync function run() {\n\tconfigureSpEnvironment();\n\tprocess.title = \"sp\";\n\tconst args = process.argv.slice(2);\n\tif (args.length === 1 && (args[0] === \"--version\" || args[0] === \"-v\")) {\n\t\tconsole.log(SP_AGENT_VERSION);\n\t\treturn;\n\t}\n\tif (args.length === 1 && (args[0] === \"--help\" || args[0] === \"-h\")) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (await handleSpReleaseCommand(args)) return;\n\tawait runSpRuntime(args);\n}\n\nrun().catch((error) => {\n\tconsole.error(`Error: ${error instanceof Error ? error.message : String(error)}`);\n\tprocess.exitCode = 1;\n});\n"]}
|
package/dist/distribution.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export declare function createSpExtensionRunnerOptions(extensions: readonly Exte
|
|
|
36
36
|
export declare function createSpMainOptions(): Promise<MainOptions>;
|
|
37
37
|
export declare const requiredExtension: {
|
|
38
38
|
readonly name: "@senpiper/sp-agent-extensions";
|
|
39
|
-
readonly version: "0.1.
|
|
40
|
-
readonly digest: "sha256:
|
|
39
|
+
readonly version: "0.1.5";
|
|
40
|
+
readonly digest: "sha256:c526026def1e6b4b5bf777b9b90583fef1d18bf0793b99821b653a592b771b48";
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=distribution.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,SAAS,EACT,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,mBAAmB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAK9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIhD,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAO5D,UAAU,yBAAyB;IAClC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,uBAAuB;IACvC,sBAAsB,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,gBAAgB,CAAC;IACjF,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAClC,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,UAAU,kCAAkC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,UAAU,4BAA6B,SAAQ,kCAAkC;IAChF,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAoDD,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,kCAAuC,QAqC/F;AAoBD,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,oCAqBrF;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,uBAAuB,GAAG,mBAAmB,CASnG;AAED,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,sBAAsB,CAevG;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC,CAqBhE;AAED,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, parse, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n\tExtension,\n\tExtensionFactory,\n\tExtensionRunnerOptions,\n\tMainOptions,\n\tModelProviderPolicy,\n} from \"@senpiper/pi-coding-agent\";\nimport type { TerminalWebBridgeOptions } from \"@senpiper/sp-agent-extensions\";\nimport { EMBEDDED_REQUIRED_EXTENSION_IDENTITY } from \"./extension-identity.generated.ts\";\nimport { createSpSessionManager } from \"./sdk.ts\";\nimport { spWriterLeases } from \"./writer-leases.ts\";\n\nexport { configureSpEnvironment } from \"./environment.ts\";\nexport { SP_AGENT_VERSION } from \"./version.ts\";\n\ndeclare const SP_AGENT_COMPILED: boolean;\n\nexport const REQUIRED_EXTENSION_OWNER = \"<inline:sp-agent>\";\n\ninterface PackageManifest {\n\tname?: string;\n\tversion?: string;\n}\n\ninterface EmbeddedExtensionIdentity {\n\trequired: { name: string; version: string };\n\tartifact: { name: string; version: string; digest: string };\n}\n\nexport interface RequiredExtensionModule {\n\tcreateSpAgentExtension: (options?: TerminalWebBridgeOptions) => ExtensionFactory;\n\thandleSpCommand: (args: string[]) => Promise<boolean>;\n\treadSpGatewayApiKey: () => unknown;\n\treadSpGatewayState: () => unknown;\n\tSP_GATEWAY_PROVIDER_ID: string;\n}\n\ninterface RequiredExtensionValidationOptions {\n\tcompiled?: boolean;\n\tembeddedIdentity?: EmbeddedExtensionIdentity;\n\tresolvedEntrypoint?: string;\n}\n\ninterface RequiredExtensionLoadOptions extends RequiredExtensionValidationOptions {\n\timportExtension?: (specifier: string) => Promise<unknown>;\n}\n\nfunction findPackageManifest(entrypoint: string) {\n\tlet directory = dirname(entrypoint);\n\tconst root = parse(directory).root;\n\twhile (directory !== root) {\n\t\tconst manifestPath = join(directory, \"package.json\");\n\t\tif (existsSync(manifestPath)) return manifestPath;\n\t\tdirectory = dirname(directory);\n\t}\n\treturn undefined;\n}\n\nfunction collectJavaScriptFiles(directory: string): string[] {\n\tconst files: string[] = [];\n\tfor (const entry of readdirSync(directory, { withFileTypes: true })) {\n\t\tconst path = join(directory, entry.name);\n\t\tif (entry.isDirectory()) files.push(...collectJavaScriptFiles(path));\n\t\telse if (entry.isFile() && entry.name.endsWith(\".js\")) files.push(path);\n\t}\n\treturn files.sort((left, right) => relative(directory, left).localeCompare(relative(directory, right)));\n}\n\nfunction digestArtifact(directory: string) {\n\tconst files = collectJavaScriptFiles(directory);\n\tif (files.length === 0) throw new Error(`Required extension artifact contains no JavaScript: ${directory}`);\n\tconst hash = createHash(\"sha256\");\n\tfor (const path of files) {\n\t\tconst artifactPath = relative(directory, path).replaceAll(\"\\\\\", \"/\");\n\t\tconst content = readFileSync(path);\n\t\thash.update(`${artifactPath}\\0${content.byteLength}\\0`);\n\t\thash.update(content);\n\t}\n\treturn `sha256:${hash.digest(\"hex\")}`;\n}\n\nfunction assertEmbeddedIdentity(identity: EmbeddedExtensionIdentity) {\n\tif (\n\t\tidentity.artifact.name !== identity.required.name ||\n\t\tidentity.artifact.version !== identity.required.version ||\n\t\t!/^sha256:[0-9a-f]{64}$/u.test(identity.artifact.digest)\n\t) {\n\t\tthrow new Error(\n\t\t\t`Required extension build identity mismatch: expected ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction isCompiledExecutable() {\n\treturn typeof SP_AGENT_COMPILED !== \"undefined\" && SP_AGENT_COMPILED;\n}\n\nexport function assertRequiredExtensionIdentity(options: RequiredExtensionValidationOptions = {}) {\n\tconst identity = options.embeddedIdentity ?? EMBEDDED_REQUIRED_EXTENSION_IDENTITY;\n\tassertEmbeddedIdentity(identity);\n\tif (options.compiled ?? isCompiledExecutable()) return;\n\n\tconst resolved = options.resolvedEntrypoint ?? import.meta.resolve(identity.required.name);\n\tif (!resolved.startsWith(\"file:\")) {\n\t\tthrow new Error(`Cannot verify required extension ${identity.required.name}: ${resolved}`);\n\t}\n\tconst entrypoint = fileURLToPath(resolved);\n\tconst manifestPath = findPackageManifest(entrypoint);\n\tif (!manifestPath) {\n\t\tthrow new Error(`Cannot find the manifest for required extension ${identity.required.name}.`);\n\t}\n\tconst packageDirectory = dirname(manifestPath);\n\tconst entrypointRelativePath = relative(packageDirectory, entrypoint);\n\tif (\n\t\tentrypointRelativePath === \"\" ||\n\t\tentrypointRelativePath === \"..\" ||\n\t\tentrypointRelativePath.startsWith(\"../\") ||\n\t\tentrypointRelativePath.startsWith(\"..\\\\\") ||\n\t\tisAbsolute(entrypointRelativePath)\n\t) {\n\t\tthrow new Error(`Required extension entrypoint is outside its package: ${entrypoint}`);\n\t}\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as PackageManifest;\n\tif (manifest.name !== identity.required.name || manifest.version !== identity.required.version) {\n\t\tthrow new Error(\n\t\t\t`Required extension mismatch: expected ${identity.required.name}@${identity.required.version}, found ${manifest.name ?? \"unknown\"}@${manifest.version ?? \"unknown\"}.`,\n\t\t);\n\t}\n\tconst digest = digestArtifact(dirname(entrypoint));\n\tif (digest !== identity.artifact.digest) {\n\t\tthrow new Error(\n\t\t\t`Required extension authenticity check failed for ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction assertRequiredExtensionExports(value: unknown): asserts value is RequiredExtensionModule {\n\tif (typeof value !== \"object\" || value === null) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n\tconst module = value as Record<string, unknown>;\n\tif (\n\t\ttypeof module.createSpAgentExtension !== \"function\" ||\n\t\ttypeof module.handleSpCommand !== \"function\" ||\n\t\ttypeof module.readSpGatewayApiKey !== \"function\" ||\n\t\ttypeof module.readSpGatewayState !== \"function\" ||\n\t\ttypeof module.SP_GATEWAY_PROVIDER_ID !== \"string\"\n\t) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n}\n\nlet requiredExtensionPromise: Promise<RequiredExtensionModule> | undefined;\n\nexport async function loadRequiredExtension(options: RequiredExtensionLoadOptions = {}) {\n\tconst usesDefaultLoader = Object.keys(options).length === 0;\n\tif (usesDefaultLoader && requiredExtensionPromise) return requiredExtensionPromise;\n\n\tassertRequiredExtensionIdentity(options);\n\tconst compiled = options.compiled ?? isCompiledExecutable();\n\tconst specifier = compiled\n\t\t? EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name\n\t\t: (options.resolvedEntrypoint ?? import.meta.resolve(EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name));\n\tconst load = async () => {\n\t\tconst imported = options.importExtension\n\t\t\t? await options.importExtension(specifier)\n\t\t\t: compiled\n\t\t\t\t? await import(\"@senpiper/sp-agent-extensions\")\n\t\t\t\t: await import(specifier);\n\t\tassertRequiredExtensionExports(imported);\n\t\treturn imported;\n\t};\n\tconst promise = load();\n\tif (usesDefaultLoader) requiredExtensionPromise = promise;\n\treturn promise;\n}\n\nexport function createSpModelProviderPolicy(extension: RequiredExtensionModule): ModelProviderPolicy {\n\tconst configured = extension.readSpGatewayState() !== undefined;\n\tif (configured) extension.readSpGatewayApiKey();\n\treturn {\n\t\tallowedProviderIds: [extension.SP_GATEWAY_PROVIDER_ID],\n\t\trequiredProviderIds: configured ? [extension.SP_GATEWAY_PROVIDER_ID] : [],\n\t\tallowModelConfiguration: false,\n\t\tproviderOwners: { [extension.SP_GATEWAY_PROVIDER_ID]: REQUIRED_EXTENSION_OWNER },\n\t};\n}\n\nexport function createSpExtensionRunnerOptions(extensions: readonly Extension[]): ExtensionRunnerOptions {\n\tconst owner = extensions.find((extension) => extension.path === REQUIRED_EXTENSION_OWNER);\n\tif (!owner) throw new Error(\"Required SP extension did not load.\");\n\treturn {\n\t\tcommandOwnership: {\n\t\t\treservedCommandNames: [\"login\", \"web\"],\n\t\t\towners: new Map([\n\t\t\t\t[\"login\", owner],\n\t\t\t\t[\"web\", owner],\n\t\t\t]),\n\t\t},\n\t\tresourceOwnership: {\n\t\t\ttoolOwners: new Map([[\"ask_user_question\", owner]]),\n\t\t},\n\t};\n}\n\nexport async function createSpMainOptions(): Promise<MainOptions> {\n\tconst extension = await loadRequiredExtension();\n\tconst sessions = await createSpSessionManager();\n\treturn {\n\t\tsessionWriterLeaseProvider: spWriterLeases,\n\t\tonSessionHistoryRoot: (root, customSessionDir) => sessions.setHistoryRoot(root, customSessionDir),\n\t\tonSessionRuntime: (runtime) => sessions.attachRuntime(runtime),\n\t\textensionFactories: [\n\t\t\t{\n\t\t\t\tname: \"sp-agent\",\n\t\t\t\tfactory: extension.createSpAgentExtension({\n\t\t\t\t\tsessions,\n\t\t\t\t\twriterLeaseVersion: 1,\n\t\t\t\t\tonReady: (bridge) => sessions.trackBridge(bridge),\n\t\t\t\t}),\n\t\t\t},\n\t\t],\n\t\tincludeBuiltInExtensions: false,\n\t\tmodelProviderPolicy: createSpModelProviderPolicy(extension),\n\t\textensionRunnerOptionsResolver: createSpExtensionRunnerOptions,\n\t};\n}\n\nexport const requiredExtension = {\n\tname: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name,\n\tversion: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.version,\n\tdigest: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.artifact.digest,\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,SAAS,EACT,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,mBAAmB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAK9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIhD,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAO5D,UAAU,yBAAyB;IAClC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,uBAAuB;IACvC,sBAAsB,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,gBAAgB,CAAC;IACjF,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAClC,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,UAAU,kCAAkC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,UAAU,4BAA6B,SAAQ,kCAAkC;IAChF,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAoDD,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,kCAAuC,QAqC/F;AAoBD,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,oCAqBrF;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,uBAAuB,GAAG,mBAAmB,CASnG;AAED,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,sBAAsB,CAevG;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC,CAqBhE;AAED,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, parse, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n\tExtension,\n\tExtensionFactory,\n\tExtensionRunnerOptions,\n\tMainOptions,\n\tModelProviderPolicy,\n} from \"@senpiper/pi-coding-agent\";\nimport type { TerminalWebBridgeOptions } from \"@senpiper/sp-agent-extensions\";\nimport { EMBEDDED_REQUIRED_EXTENSION_IDENTITY } from \"./extension-identity.generated.ts\";\nimport { createSpSessionManager } from \"./sdk.ts\";\nimport { spWriterLeases } from \"./writer-leases.ts\";\n\nexport { configureSpEnvironment } from \"./environment.ts\";\nexport { SP_AGENT_VERSION } from \"./version.ts\";\n\ndeclare const SP_AGENT_COMPILED: boolean;\n\nexport const REQUIRED_EXTENSION_OWNER = \"<inline:sp-agent>\";\n\ninterface PackageManifest {\n\tname?: string;\n\tversion?: string;\n}\n\ninterface EmbeddedExtensionIdentity {\n\trequired: { name: string; version: string };\n\tartifact: { name: string; version: string; digest: string };\n}\n\nexport interface RequiredExtensionModule {\n\tcreateSpAgentExtension: (options?: TerminalWebBridgeOptions) => ExtensionFactory;\n\thandleSpCommand: (args: string[]) => Promise<boolean>;\n\treadSpGatewayApiKey: () => unknown;\n\treadSpGatewayState: () => unknown;\n\tSP_GATEWAY_PROVIDER_ID: string;\n}\n\ninterface RequiredExtensionValidationOptions {\n\tcompiled?: boolean;\n\tembeddedIdentity?: EmbeddedExtensionIdentity;\n\tresolvedEntrypoint?: string;\n}\n\ninterface RequiredExtensionLoadOptions extends RequiredExtensionValidationOptions {\n\timportExtension?: (specifier: string) => Promise<unknown>;\n}\n\nfunction findPackageManifest(entrypoint: string) {\n\tlet directory = dirname(entrypoint);\n\tconst root = parse(directory).root;\n\twhile (directory !== root) {\n\t\tconst manifestPath = join(directory, \"package.json\");\n\t\tif (existsSync(manifestPath)) return manifestPath;\n\t\tdirectory = dirname(directory);\n\t}\n\treturn undefined;\n}\n\nfunction collectJavaScriptFiles(directory: string): string[] {\n\tconst files: string[] = [];\n\tfor (const entry of readdirSync(directory, { withFileTypes: true })) {\n\t\tconst path = join(directory, entry.name);\n\t\tif (entry.isDirectory()) files.push(...collectJavaScriptFiles(path));\n\t\telse if (entry.isFile() && entry.name.endsWith(\".js\")) files.push(path);\n\t}\n\treturn files.sort((left, right) => relative(directory, left).localeCompare(relative(directory, right)));\n}\n\nfunction digestArtifact(directory: string) {\n\tconst files = collectJavaScriptFiles(directory);\n\tif (files.length === 0) throw new Error(`Required extension artifact contains no JavaScript: ${directory}`);\n\tconst hash = createHash(\"sha256\");\n\tfor (const path of files) {\n\t\tconst artifactPath = relative(directory, path).replaceAll(\"\\\\\", \"/\");\n\t\tconst content = readFileSync(path);\n\t\thash.update(`${artifactPath}\\0${content.byteLength}\\0`);\n\t\thash.update(content);\n\t}\n\treturn `sha256:${hash.digest(\"hex\")}`;\n}\n\nfunction assertEmbeddedIdentity(identity: EmbeddedExtensionIdentity) {\n\tif (\n\t\tidentity.artifact.name !== identity.required.name ||\n\t\tidentity.artifact.version !== identity.required.version ||\n\t\t!/^sha256:[0-9a-f]{64}$/u.test(identity.artifact.digest)\n\t) {\n\t\tthrow new Error(\n\t\t\t`Required extension build identity mismatch: expected ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction isCompiledExecutable() {\n\treturn typeof SP_AGENT_COMPILED !== \"undefined\" && SP_AGENT_COMPILED;\n}\n\nexport function assertRequiredExtensionIdentity(options: RequiredExtensionValidationOptions = {}) {\n\tconst identity = options.embeddedIdentity ?? EMBEDDED_REQUIRED_EXTENSION_IDENTITY;\n\tassertEmbeddedIdentity(identity);\n\tif (options.compiled ?? isCompiledExecutable()) return;\n\n\tconst resolved = options.resolvedEntrypoint ?? import.meta.resolve(identity.required.name);\n\tif (!resolved.startsWith(\"file:\")) {\n\t\tthrow new Error(`Cannot verify required extension ${identity.required.name}: ${resolved}`);\n\t}\n\tconst entrypoint = fileURLToPath(resolved);\n\tconst manifestPath = findPackageManifest(entrypoint);\n\tif (!manifestPath) {\n\t\tthrow new Error(`Cannot find the manifest for required extension ${identity.required.name}.`);\n\t}\n\tconst packageDirectory = dirname(manifestPath);\n\tconst entrypointRelativePath = relative(packageDirectory, entrypoint);\n\tif (\n\t\tentrypointRelativePath === \"\" ||\n\t\tentrypointRelativePath === \"..\" ||\n\t\tentrypointRelativePath.startsWith(\"../\") ||\n\t\tentrypointRelativePath.startsWith(\"..\\\\\") ||\n\t\tisAbsolute(entrypointRelativePath)\n\t) {\n\t\tthrow new Error(`Required extension entrypoint is outside its package: ${entrypoint}`);\n\t}\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as PackageManifest;\n\tif (manifest.name !== identity.required.name || manifest.version !== identity.required.version) {\n\t\tthrow new Error(\n\t\t\t`Required extension mismatch: expected ${identity.required.name}@${identity.required.version}, found ${manifest.name ?? \"unknown\"}@${manifest.version ?? \"unknown\"}.`,\n\t\t);\n\t}\n\tconst digest = digestArtifact(dirname(entrypoint));\n\tif (digest !== identity.artifact.digest) {\n\t\tthrow new Error(\n\t\t\t`Required extension authenticity check failed for ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction assertRequiredExtensionExports(value: unknown): asserts value is RequiredExtensionModule {\n\tif (typeof value !== \"object\" || value === null) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n\tconst module = value as Record<string, unknown>;\n\tif (\n\t\ttypeof module.createSpAgentExtension !== \"function\" ||\n\t\ttypeof module.handleSpCommand !== \"function\" ||\n\t\ttypeof module.readSpGatewayApiKey !== \"function\" ||\n\t\ttypeof module.readSpGatewayState !== \"function\" ||\n\t\ttypeof module.SP_GATEWAY_PROVIDER_ID !== \"string\"\n\t) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n}\n\nlet requiredExtensionPromise: Promise<RequiredExtensionModule> | undefined;\n\nexport async function loadRequiredExtension(options: RequiredExtensionLoadOptions = {}) {\n\tconst usesDefaultLoader = Object.keys(options).length === 0;\n\tif (usesDefaultLoader && requiredExtensionPromise) return requiredExtensionPromise;\n\n\tassertRequiredExtensionIdentity(options);\n\tconst compiled = options.compiled ?? isCompiledExecutable();\n\tconst specifier = compiled\n\t\t? EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name\n\t\t: (options.resolvedEntrypoint ?? import.meta.resolve(EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name));\n\tconst load = async () => {\n\t\tconst imported = options.importExtension\n\t\t\t? await options.importExtension(specifier)\n\t\t\t: compiled\n\t\t\t\t? await import(\"@senpiper/sp-agent-extensions\")\n\t\t\t\t: await import(specifier);\n\t\tassertRequiredExtensionExports(imported);\n\t\treturn imported;\n\t};\n\tconst promise = load();\n\tif (usesDefaultLoader) requiredExtensionPromise = promise;\n\treturn promise;\n}\n\nexport function createSpModelProviderPolicy(extension: RequiredExtensionModule): ModelProviderPolicy {\n\tconst configured = extension.readSpGatewayState() !== undefined;\n\tif (configured) extension.readSpGatewayApiKey();\n\treturn {\n\t\tallowedProviderIds: [extension.SP_GATEWAY_PROVIDER_ID],\n\t\trequiredProviderIds: configured ? [extension.SP_GATEWAY_PROVIDER_ID] : [],\n\t\tallowModelConfiguration: false,\n\t\tproviderOwners: { [extension.SP_GATEWAY_PROVIDER_ID]: REQUIRED_EXTENSION_OWNER },\n\t};\n}\n\nexport function createSpExtensionRunnerOptions(extensions: readonly Extension[]): ExtensionRunnerOptions {\n\tconst owner = extensions.find((extension) => extension.path === REQUIRED_EXTENSION_OWNER);\n\tif (!owner) throw new Error(\"Required Senpiper Workbench extension did not load.\");\n\treturn {\n\t\tcommandOwnership: {\n\t\t\treservedCommandNames: [\"login\", \"web\"],\n\t\t\towners: new Map([\n\t\t\t\t[\"login\", owner],\n\t\t\t\t[\"web\", owner],\n\t\t\t]),\n\t\t},\n\t\tresourceOwnership: {\n\t\t\ttoolOwners: new Map([[\"ask_user_question\", owner]]),\n\t\t},\n\t};\n}\n\nexport async function createSpMainOptions(): Promise<MainOptions> {\n\tconst extension = await loadRequiredExtension();\n\tconst sessions = await createSpSessionManager();\n\treturn {\n\t\tsessionWriterLeaseProvider: spWriterLeases,\n\t\tonSessionHistoryRoot: (root, customSessionDir) => sessions.setHistoryRoot(root, customSessionDir),\n\t\tonSessionRuntime: (runtime) => sessions.attachRuntime(runtime),\n\t\textensionFactories: [\n\t\t\t{\n\t\t\t\tname: \"sp-agent\",\n\t\t\t\tfactory: extension.createSpAgentExtension({\n\t\t\t\t\tsessions,\n\t\t\t\t\twriterLeaseVersion: 1,\n\t\t\t\t\tonReady: (bridge) => sessions.trackBridge(bridge),\n\t\t\t\t}),\n\t\t\t},\n\t\t],\n\t\tincludeBuiltInExtensions: false,\n\t\tmodelProviderPolicy: createSpModelProviderPolicy(extension),\n\t\textensionRunnerOptionsResolver: createSpExtensionRunnerOptions,\n\t};\n}\n\nexport const requiredExtension = {\n\tname: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name,\n\tversion: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.version,\n\tdigest: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.artifact.digest,\n} as const;\n"]}
|
package/dist/distribution.js
CHANGED
|
@@ -144,7 +144,7 @@ export function createSpModelProviderPolicy(extension) {
|
|
|
144
144
|
export function createSpExtensionRunnerOptions(extensions) {
|
|
145
145
|
const owner = extensions.find((extension) => extension.path === REQUIRED_EXTENSION_OWNER);
|
|
146
146
|
if (!owner)
|
|
147
|
-
throw new Error("Required
|
|
147
|
+
throw new Error("Required Senpiper Workbench extension did not load.");
|
|
148
148
|
return {
|
|
149
149
|
commandOwnership: {
|
|
150
150
|
reservedCommandNames: ["login", "web"],
|
package/dist/distribution.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distribution.js","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, parse, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n\tExtension,\n\tExtensionFactory,\n\tExtensionRunnerOptions,\n\tMainOptions,\n\tModelProviderPolicy,\n} from \"@senpiper/pi-coding-agent\";\nimport type { TerminalWebBridgeOptions } from \"@senpiper/sp-agent-extensions\";\nimport { EMBEDDED_REQUIRED_EXTENSION_IDENTITY } from \"./extension-identity.generated.ts\";\nimport { createSpSessionManager } from \"./sdk.ts\";\nimport { spWriterLeases } from \"./writer-leases.ts\";\n\nexport { configureSpEnvironment } from \"./environment.ts\";\nexport { SP_AGENT_VERSION } from \"./version.ts\";\n\ndeclare const SP_AGENT_COMPILED: boolean;\n\nexport const REQUIRED_EXTENSION_OWNER = \"<inline:sp-agent>\";\n\ninterface PackageManifest {\n\tname?: string;\n\tversion?: string;\n}\n\ninterface EmbeddedExtensionIdentity {\n\trequired: { name: string; version: string };\n\tartifact: { name: string; version: string; digest: string };\n}\n\nexport interface RequiredExtensionModule {\n\tcreateSpAgentExtension: (options?: TerminalWebBridgeOptions) => ExtensionFactory;\n\thandleSpCommand: (args: string[]) => Promise<boolean>;\n\treadSpGatewayApiKey: () => unknown;\n\treadSpGatewayState: () => unknown;\n\tSP_GATEWAY_PROVIDER_ID: string;\n}\n\ninterface RequiredExtensionValidationOptions {\n\tcompiled?: boolean;\n\tembeddedIdentity?: EmbeddedExtensionIdentity;\n\tresolvedEntrypoint?: string;\n}\n\ninterface RequiredExtensionLoadOptions extends RequiredExtensionValidationOptions {\n\timportExtension?: (specifier: string) => Promise<unknown>;\n}\n\nfunction findPackageManifest(entrypoint: string) {\n\tlet directory = dirname(entrypoint);\n\tconst root = parse(directory).root;\n\twhile (directory !== root) {\n\t\tconst manifestPath = join(directory, \"package.json\");\n\t\tif (existsSync(manifestPath)) return manifestPath;\n\t\tdirectory = dirname(directory);\n\t}\n\treturn undefined;\n}\n\nfunction collectJavaScriptFiles(directory: string): string[] {\n\tconst files: string[] = [];\n\tfor (const entry of readdirSync(directory, { withFileTypes: true })) {\n\t\tconst path = join(directory, entry.name);\n\t\tif (entry.isDirectory()) files.push(...collectJavaScriptFiles(path));\n\t\telse if (entry.isFile() && entry.name.endsWith(\".js\")) files.push(path);\n\t}\n\treturn files.sort((left, right) => relative(directory, left).localeCompare(relative(directory, right)));\n}\n\nfunction digestArtifact(directory: string) {\n\tconst files = collectJavaScriptFiles(directory);\n\tif (files.length === 0) throw new Error(`Required extension artifact contains no JavaScript: ${directory}`);\n\tconst hash = createHash(\"sha256\");\n\tfor (const path of files) {\n\t\tconst artifactPath = relative(directory, path).replaceAll(\"\\\\\", \"/\");\n\t\tconst content = readFileSync(path);\n\t\thash.update(`${artifactPath}\\0${content.byteLength}\\0`);\n\t\thash.update(content);\n\t}\n\treturn `sha256:${hash.digest(\"hex\")}`;\n}\n\nfunction assertEmbeddedIdentity(identity: EmbeddedExtensionIdentity) {\n\tif (\n\t\tidentity.artifact.name !== identity.required.name ||\n\t\tidentity.artifact.version !== identity.required.version ||\n\t\t!/^sha256:[0-9a-f]{64}$/u.test(identity.artifact.digest)\n\t) {\n\t\tthrow new Error(\n\t\t\t`Required extension build identity mismatch: expected ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction isCompiledExecutable() {\n\treturn typeof SP_AGENT_COMPILED !== \"undefined\" && SP_AGENT_COMPILED;\n}\n\nexport function assertRequiredExtensionIdentity(options: RequiredExtensionValidationOptions = {}) {\n\tconst identity = options.embeddedIdentity ?? EMBEDDED_REQUIRED_EXTENSION_IDENTITY;\n\tassertEmbeddedIdentity(identity);\n\tif (options.compiled ?? isCompiledExecutable()) return;\n\n\tconst resolved = options.resolvedEntrypoint ?? import.meta.resolve(identity.required.name);\n\tif (!resolved.startsWith(\"file:\")) {\n\t\tthrow new Error(`Cannot verify required extension ${identity.required.name}: ${resolved}`);\n\t}\n\tconst entrypoint = fileURLToPath(resolved);\n\tconst manifestPath = findPackageManifest(entrypoint);\n\tif (!manifestPath) {\n\t\tthrow new Error(`Cannot find the manifest for required extension ${identity.required.name}.`);\n\t}\n\tconst packageDirectory = dirname(manifestPath);\n\tconst entrypointRelativePath = relative(packageDirectory, entrypoint);\n\tif (\n\t\tentrypointRelativePath === \"\" ||\n\t\tentrypointRelativePath === \"..\" ||\n\t\tentrypointRelativePath.startsWith(\"../\") ||\n\t\tentrypointRelativePath.startsWith(\"..\\\\\") ||\n\t\tisAbsolute(entrypointRelativePath)\n\t) {\n\t\tthrow new Error(`Required extension entrypoint is outside its package: ${entrypoint}`);\n\t}\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as PackageManifest;\n\tif (manifest.name !== identity.required.name || manifest.version !== identity.required.version) {\n\t\tthrow new Error(\n\t\t\t`Required extension mismatch: expected ${identity.required.name}@${identity.required.version}, found ${manifest.name ?? \"unknown\"}@${manifest.version ?? \"unknown\"}.`,\n\t\t);\n\t}\n\tconst digest = digestArtifact(dirname(entrypoint));\n\tif (digest !== identity.artifact.digest) {\n\t\tthrow new Error(\n\t\t\t`Required extension authenticity check failed for ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction assertRequiredExtensionExports(value: unknown): asserts value is RequiredExtensionModule {\n\tif (typeof value !== \"object\" || value === null) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n\tconst module = value as Record<string, unknown>;\n\tif (\n\t\ttypeof module.createSpAgentExtension !== \"function\" ||\n\t\ttypeof module.handleSpCommand !== \"function\" ||\n\t\ttypeof module.readSpGatewayApiKey !== \"function\" ||\n\t\ttypeof module.readSpGatewayState !== \"function\" ||\n\t\ttypeof module.SP_GATEWAY_PROVIDER_ID !== \"string\"\n\t) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n}\n\nlet requiredExtensionPromise: Promise<RequiredExtensionModule> | undefined;\n\nexport async function loadRequiredExtension(options: RequiredExtensionLoadOptions = {}) {\n\tconst usesDefaultLoader = Object.keys(options).length === 0;\n\tif (usesDefaultLoader && requiredExtensionPromise) return requiredExtensionPromise;\n\n\tassertRequiredExtensionIdentity(options);\n\tconst compiled = options.compiled ?? isCompiledExecutable();\n\tconst specifier = compiled\n\t\t? EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name\n\t\t: (options.resolvedEntrypoint ?? import.meta.resolve(EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name));\n\tconst load = async () => {\n\t\tconst imported = options.importExtension\n\t\t\t? await options.importExtension(specifier)\n\t\t\t: compiled\n\t\t\t\t? await import(\"@senpiper/sp-agent-extensions\")\n\t\t\t\t: await import(specifier);\n\t\tassertRequiredExtensionExports(imported);\n\t\treturn imported;\n\t};\n\tconst promise = load();\n\tif (usesDefaultLoader) requiredExtensionPromise = promise;\n\treturn promise;\n}\n\nexport function createSpModelProviderPolicy(extension: RequiredExtensionModule): ModelProviderPolicy {\n\tconst configured = extension.readSpGatewayState() !== undefined;\n\tif (configured) extension.readSpGatewayApiKey();\n\treturn {\n\t\tallowedProviderIds: [extension.SP_GATEWAY_PROVIDER_ID],\n\t\trequiredProviderIds: configured ? [extension.SP_GATEWAY_PROVIDER_ID] : [],\n\t\tallowModelConfiguration: false,\n\t\tproviderOwners: { [extension.SP_GATEWAY_PROVIDER_ID]: REQUIRED_EXTENSION_OWNER },\n\t};\n}\n\nexport function createSpExtensionRunnerOptions(extensions: readonly Extension[]): ExtensionRunnerOptions {\n\tconst owner = extensions.find((extension) => extension.path === REQUIRED_EXTENSION_OWNER);\n\tif (!owner) throw new Error(\"Required SP extension did not load.\");\n\treturn {\n\t\tcommandOwnership: {\n\t\t\treservedCommandNames: [\"login\", \"web\"],\n\t\t\towners: new Map([\n\t\t\t\t[\"login\", owner],\n\t\t\t\t[\"web\", owner],\n\t\t\t]),\n\t\t},\n\t\tresourceOwnership: {\n\t\t\ttoolOwners: new Map([[\"ask_user_question\", owner]]),\n\t\t},\n\t};\n}\n\nexport async function createSpMainOptions(): Promise<MainOptions> {\n\tconst extension = await loadRequiredExtension();\n\tconst sessions = await createSpSessionManager();\n\treturn {\n\t\tsessionWriterLeaseProvider: spWriterLeases,\n\t\tonSessionHistoryRoot: (root, customSessionDir) => sessions.setHistoryRoot(root, customSessionDir),\n\t\tonSessionRuntime: (runtime) => sessions.attachRuntime(runtime),\n\t\textensionFactories: [\n\t\t\t{\n\t\t\t\tname: \"sp-agent\",\n\t\t\t\tfactory: extension.createSpAgentExtension({\n\t\t\t\t\tsessions,\n\t\t\t\t\twriterLeaseVersion: 1,\n\t\t\t\t\tonReady: (bridge) => sessions.trackBridge(bridge),\n\t\t\t\t}),\n\t\t\t},\n\t\t],\n\t\tincludeBuiltInExtensions: false,\n\t\tmodelProviderPolicy: createSpModelProviderPolicy(extension),\n\t\textensionRunnerOptionsResolver: createSpExtensionRunnerOptions,\n\t};\n}\n\nexport const requiredExtension = {\n\tname: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name,\n\tversion: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.version,\n\tdigest: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.artifact.digest,\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"distribution.js","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, parse, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n\tExtension,\n\tExtensionFactory,\n\tExtensionRunnerOptions,\n\tMainOptions,\n\tModelProviderPolicy,\n} from \"@senpiper/pi-coding-agent\";\nimport type { TerminalWebBridgeOptions } from \"@senpiper/sp-agent-extensions\";\nimport { EMBEDDED_REQUIRED_EXTENSION_IDENTITY } from \"./extension-identity.generated.ts\";\nimport { createSpSessionManager } from \"./sdk.ts\";\nimport { spWriterLeases } from \"./writer-leases.ts\";\n\nexport { configureSpEnvironment } from \"./environment.ts\";\nexport { SP_AGENT_VERSION } from \"./version.ts\";\n\ndeclare const SP_AGENT_COMPILED: boolean;\n\nexport const REQUIRED_EXTENSION_OWNER = \"<inline:sp-agent>\";\n\ninterface PackageManifest {\n\tname?: string;\n\tversion?: string;\n}\n\ninterface EmbeddedExtensionIdentity {\n\trequired: { name: string; version: string };\n\tartifact: { name: string; version: string; digest: string };\n}\n\nexport interface RequiredExtensionModule {\n\tcreateSpAgentExtension: (options?: TerminalWebBridgeOptions) => ExtensionFactory;\n\thandleSpCommand: (args: string[]) => Promise<boolean>;\n\treadSpGatewayApiKey: () => unknown;\n\treadSpGatewayState: () => unknown;\n\tSP_GATEWAY_PROVIDER_ID: string;\n}\n\ninterface RequiredExtensionValidationOptions {\n\tcompiled?: boolean;\n\tembeddedIdentity?: EmbeddedExtensionIdentity;\n\tresolvedEntrypoint?: string;\n}\n\ninterface RequiredExtensionLoadOptions extends RequiredExtensionValidationOptions {\n\timportExtension?: (specifier: string) => Promise<unknown>;\n}\n\nfunction findPackageManifest(entrypoint: string) {\n\tlet directory = dirname(entrypoint);\n\tconst root = parse(directory).root;\n\twhile (directory !== root) {\n\t\tconst manifestPath = join(directory, \"package.json\");\n\t\tif (existsSync(manifestPath)) return manifestPath;\n\t\tdirectory = dirname(directory);\n\t}\n\treturn undefined;\n}\n\nfunction collectJavaScriptFiles(directory: string): string[] {\n\tconst files: string[] = [];\n\tfor (const entry of readdirSync(directory, { withFileTypes: true })) {\n\t\tconst path = join(directory, entry.name);\n\t\tif (entry.isDirectory()) files.push(...collectJavaScriptFiles(path));\n\t\telse if (entry.isFile() && entry.name.endsWith(\".js\")) files.push(path);\n\t}\n\treturn files.sort((left, right) => relative(directory, left).localeCompare(relative(directory, right)));\n}\n\nfunction digestArtifact(directory: string) {\n\tconst files = collectJavaScriptFiles(directory);\n\tif (files.length === 0) throw new Error(`Required extension artifact contains no JavaScript: ${directory}`);\n\tconst hash = createHash(\"sha256\");\n\tfor (const path of files) {\n\t\tconst artifactPath = relative(directory, path).replaceAll(\"\\\\\", \"/\");\n\t\tconst content = readFileSync(path);\n\t\thash.update(`${artifactPath}\\0${content.byteLength}\\0`);\n\t\thash.update(content);\n\t}\n\treturn `sha256:${hash.digest(\"hex\")}`;\n}\n\nfunction assertEmbeddedIdentity(identity: EmbeddedExtensionIdentity) {\n\tif (\n\t\tidentity.artifact.name !== identity.required.name ||\n\t\tidentity.artifact.version !== identity.required.version ||\n\t\t!/^sha256:[0-9a-f]{64}$/u.test(identity.artifact.digest)\n\t) {\n\t\tthrow new Error(\n\t\t\t`Required extension build identity mismatch: expected ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction isCompiledExecutable() {\n\treturn typeof SP_AGENT_COMPILED !== \"undefined\" && SP_AGENT_COMPILED;\n}\n\nexport function assertRequiredExtensionIdentity(options: RequiredExtensionValidationOptions = {}) {\n\tconst identity = options.embeddedIdentity ?? EMBEDDED_REQUIRED_EXTENSION_IDENTITY;\n\tassertEmbeddedIdentity(identity);\n\tif (options.compiled ?? isCompiledExecutable()) return;\n\n\tconst resolved = options.resolvedEntrypoint ?? import.meta.resolve(identity.required.name);\n\tif (!resolved.startsWith(\"file:\")) {\n\t\tthrow new Error(`Cannot verify required extension ${identity.required.name}: ${resolved}`);\n\t}\n\tconst entrypoint = fileURLToPath(resolved);\n\tconst manifestPath = findPackageManifest(entrypoint);\n\tif (!manifestPath) {\n\t\tthrow new Error(`Cannot find the manifest for required extension ${identity.required.name}.`);\n\t}\n\tconst packageDirectory = dirname(manifestPath);\n\tconst entrypointRelativePath = relative(packageDirectory, entrypoint);\n\tif (\n\t\tentrypointRelativePath === \"\" ||\n\t\tentrypointRelativePath === \"..\" ||\n\t\tentrypointRelativePath.startsWith(\"../\") ||\n\t\tentrypointRelativePath.startsWith(\"..\\\\\") ||\n\t\tisAbsolute(entrypointRelativePath)\n\t) {\n\t\tthrow new Error(`Required extension entrypoint is outside its package: ${entrypoint}`);\n\t}\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as PackageManifest;\n\tif (manifest.name !== identity.required.name || manifest.version !== identity.required.version) {\n\t\tthrow new Error(\n\t\t\t`Required extension mismatch: expected ${identity.required.name}@${identity.required.version}, found ${manifest.name ?? \"unknown\"}@${manifest.version ?? \"unknown\"}.`,\n\t\t);\n\t}\n\tconst digest = digestArtifact(dirname(entrypoint));\n\tif (digest !== identity.artifact.digest) {\n\t\tthrow new Error(\n\t\t\t`Required extension authenticity check failed for ${identity.required.name}@${identity.required.version}.`,\n\t\t);\n\t}\n}\n\nfunction assertRequiredExtensionExports(value: unknown): asserts value is RequiredExtensionModule {\n\tif (typeof value !== \"object\" || value === null) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n\tconst module = value as Record<string, unknown>;\n\tif (\n\t\ttypeof module.createSpAgentExtension !== \"function\" ||\n\t\ttypeof module.handleSpCommand !== \"function\" ||\n\t\ttypeof module.readSpGatewayApiKey !== \"function\" ||\n\t\ttypeof module.readSpGatewayState !== \"function\" ||\n\t\ttypeof module.SP_GATEWAY_PROVIDER_ID !== \"string\"\n\t) {\n\t\tthrow new Error(`Required extension ${requiredExtension.name}@${requiredExtension.version} is invalid.`);\n\t}\n}\n\nlet requiredExtensionPromise: Promise<RequiredExtensionModule> | undefined;\n\nexport async function loadRequiredExtension(options: RequiredExtensionLoadOptions = {}) {\n\tconst usesDefaultLoader = Object.keys(options).length === 0;\n\tif (usesDefaultLoader && requiredExtensionPromise) return requiredExtensionPromise;\n\n\tassertRequiredExtensionIdentity(options);\n\tconst compiled = options.compiled ?? isCompiledExecutable();\n\tconst specifier = compiled\n\t\t? EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name\n\t\t: (options.resolvedEntrypoint ?? import.meta.resolve(EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name));\n\tconst load = async () => {\n\t\tconst imported = options.importExtension\n\t\t\t? await options.importExtension(specifier)\n\t\t\t: compiled\n\t\t\t\t? await import(\"@senpiper/sp-agent-extensions\")\n\t\t\t\t: await import(specifier);\n\t\tassertRequiredExtensionExports(imported);\n\t\treturn imported;\n\t};\n\tconst promise = load();\n\tif (usesDefaultLoader) requiredExtensionPromise = promise;\n\treturn promise;\n}\n\nexport function createSpModelProviderPolicy(extension: RequiredExtensionModule): ModelProviderPolicy {\n\tconst configured = extension.readSpGatewayState() !== undefined;\n\tif (configured) extension.readSpGatewayApiKey();\n\treturn {\n\t\tallowedProviderIds: [extension.SP_GATEWAY_PROVIDER_ID],\n\t\trequiredProviderIds: configured ? [extension.SP_GATEWAY_PROVIDER_ID] : [],\n\t\tallowModelConfiguration: false,\n\t\tproviderOwners: { [extension.SP_GATEWAY_PROVIDER_ID]: REQUIRED_EXTENSION_OWNER },\n\t};\n}\n\nexport function createSpExtensionRunnerOptions(extensions: readonly Extension[]): ExtensionRunnerOptions {\n\tconst owner = extensions.find((extension) => extension.path === REQUIRED_EXTENSION_OWNER);\n\tif (!owner) throw new Error(\"Required Senpiper Workbench extension did not load.\");\n\treturn {\n\t\tcommandOwnership: {\n\t\t\treservedCommandNames: [\"login\", \"web\"],\n\t\t\towners: new Map([\n\t\t\t\t[\"login\", owner],\n\t\t\t\t[\"web\", owner],\n\t\t\t]),\n\t\t},\n\t\tresourceOwnership: {\n\t\t\ttoolOwners: new Map([[\"ask_user_question\", owner]]),\n\t\t},\n\t};\n}\n\nexport async function createSpMainOptions(): Promise<MainOptions> {\n\tconst extension = await loadRequiredExtension();\n\tconst sessions = await createSpSessionManager();\n\treturn {\n\t\tsessionWriterLeaseProvider: spWriterLeases,\n\t\tonSessionHistoryRoot: (root, customSessionDir) => sessions.setHistoryRoot(root, customSessionDir),\n\t\tonSessionRuntime: (runtime) => sessions.attachRuntime(runtime),\n\t\textensionFactories: [\n\t\t\t{\n\t\t\t\tname: \"sp-agent\",\n\t\t\t\tfactory: extension.createSpAgentExtension({\n\t\t\t\t\tsessions,\n\t\t\t\t\twriterLeaseVersion: 1,\n\t\t\t\t\tonReady: (bridge) => sessions.trackBridge(bridge),\n\t\t\t\t}),\n\t\t\t},\n\t\t],\n\t\tincludeBuiltInExtensions: false,\n\t\tmodelProviderPolicy: createSpModelProviderPolicy(extension),\n\t\textensionRunnerOptionsResolver: createSpExtensionRunnerOptions,\n\t};\n}\n\nexport const requiredExtension = {\n\tname: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.name,\n\tversion: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.required.version,\n\tdigest: EMBEDDED_REQUIRED_EXTENSION_IDENTITY.artifact.digest,\n} as const;\n"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export declare const EMBEDDED_REQUIRED_EXTENSION_IDENTITY: {
|
|
2
2
|
readonly required: {
|
|
3
3
|
readonly name: "@senpiper/sp-agent-extensions";
|
|
4
|
-
readonly version: "0.1.
|
|
4
|
+
readonly version: "0.1.5";
|
|
5
5
|
};
|
|
6
6
|
readonly artifact: {
|
|
7
7
|
readonly name: "@senpiper/sp-agent-extensions";
|
|
8
|
-
readonly version: "0.1.
|
|
9
|
-
readonly digest: "sha256:
|
|
8
|
+
readonly version: "0.1.5";
|
|
9
|
+
readonly digest: "sha256:c526026def1e6b4b5bf777b9b90583fef1d18bf0793b99821b653a592b771b48";
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
//# sourceMappingURL=extension-identity.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-identity.generated.d.ts","sourceRoot":"","sources":["../src/extension-identity.generated.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,oCAAoC;;;;;;;;;;CAUvC,CAAC","sourcesContent":["// Generated by scripts/generate-sp-extension-identity.mjs. Do not edit.\nexport const EMBEDDED_REQUIRED_EXTENSION_IDENTITY = {\n\trequired: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.
|
|
1
|
+
{"version":3,"file":"extension-identity.generated.d.ts","sourceRoot":"","sources":["../src/extension-identity.generated.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,oCAAoC;;;;;;;;;;CAUvC,CAAC","sourcesContent":["// Generated by scripts/generate-sp-extension-identity.mjs. Do not edit.\nexport const EMBEDDED_REQUIRED_EXTENSION_IDENTITY = {\n\trequired: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.5\",\n\t},\n\tartifact: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.5\",\n\t\tdigest: \"sha256:c526026def1e6b4b5bf777b9b90583fef1d18bf0793b99821b653a592b771b48\",\n\t},\n} as const;\n"]}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
export const EMBEDDED_REQUIRED_EXTENSION_IDENTITY = {
|
|
3
3
|
required: {
|
|
4
4
|
name: "@senpiper/sp-agent-extensions",
|
|
5
|
-
version: "0.1.
|
|
5
|
+
version: "0.1.5",
|
|
6
6
|
},
|
|
7
7
|
artifact: {
|
|
8
8
|
name: "@senpiper/sp-agent-extensions",
|
|
9
|
-
version: "0.1.
|
|
10
|
-
digest: "sha256:
|
|
9
|
+
version: "0.1.5",
|
|
10
|
+
digest: "sha256:c526026def1e6b4b5bf777b9b90583fef1d18bf0793b99821b653a592b771b48",
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=extension-identity.generated.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-identity.generated.js","sourceRoot":"","sources":["../src/extension-identity.generated.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,oCAAoC,GAAG;IACnD,QAAQ,EAAE;QACT,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,OAAO;KAChB;IACD,QAAQ,EAAE;QACT,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,yEAAyE;KACjF;CACQ,CAAC","sourcesContent":["// Generated by scripts/generate-sp-extension-identity.mjs. Do not edit.\nexport const EMBEDDED_REQUIRED_EXTENSION_IDENTITY = {\n\trequired: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.
|
|
1
|
+
{"version":3,"file":"extension-identity.generated.js","sourceRoot":"","sources":["../src/extension-identity.generated.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,oCAAoC,GAAG;IACnD,QAAQ,EAAE;QACT,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,OAAO;KAChB;IACD,QAAQ,EAAE;QACT,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,yEAAyE;KACjF;CACQ,CAAC","sourcesContent":["// Generated by scripts/generate-sp-extension-identity.mjs. Do not edit.\nexport const EMBEDDED_REQUIRED_EXTENSION_IDENTITY = {\n\trequired: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.5\",\n\t},\n\tartifact: {\n\t\tname: \"@senpiper/sp-agent-extensions\",\n\t\tversion: \"0.1.5\",\n\t\tdigest: \"sha256:c526026def1e6b4b5bf777b9b90583fef1d18bf0793b99821b653a592b771b48\",\n\t},\n} as const;\n"]}
|
package/dist/install-sp.sh
CHANGED
|
@@ -157,17 +157,17 @@ EOF
|
|
|
157
157
|
|
|
158
158
|
rollback() {
|
|
159
159
|
need readlink
|
|
160
|
-
[ -L "$APP_DIR/current" ] || { echo "No active
|
|
161
|
-
[ -L "$APP_DIR/previous" ] || { echo "No previous
|
|
160
|
+
[ -L "$APP_DIR/current" ] || { echo "No active Senpiper Workbench release." >&2; exit 1; }
|
|
161
|
+
[ -L "$APP_DIR/previous" ] || { echo "No previous Senpiper Workbench release is available." >&2; exit 1; }
|
|
162
162
|
current="$(readlink "$APP_DIR/current")"
|
|
163
163
|
previous="$(readlink "$APP_DIR/previous")"
|
|
164
164
|
candidate="$APP_DIR/$previous/sp"
|
|
165
|
-
[ -x "$candidate" ] || { echo "Previous
|
|
165
|
+
[ -x "$candidate" ] || { echo "Previous Senpiper Workbench release is incomplete: $candidate" >&2; exit 1; }
|
|
166
166
|
"$candidate" --health-check >/dev/null
|
|
167
167
|
switch_pointer current "$previous"
|
|
168
168
|
switch_pointer previous "$current"
|
|
169
169
|
install_launcher
|
|
170
|
-
echo "Rolled back
|
|
170
|
+
echo "Rolled back Senpiper Workbench to $previous"
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
case "$MODE" in
|
|
@@ -180,7 +180,7 @@ esac
|
|
|
180
180
|
if [ "$DEVELOPMENT_MODE" = "1" ]; then
|
|
181
181
|
echo "Set SP_RELEASE_API_URL for explicit local-development installation." >&2
|
|
182
182
|
else
|
|
183
|
-
echo "This
|
|
183
|
+
echo "This Senpiper Workbench installer has no build-baked release API URL; refusing caller-controlled trust roots." >&2
|
|
184
184
|
fi
|
|
185
185
|
exit 1
|
|
186
186
|
}
|
|
@@ -192,11 +192,11 @@ need find
|
|
|
192
192
|
need awk
|
|
193
193
|
need cut
|
|
194
194
|
if ! RELEASE_API_ORIGIN="$(url_origin "$RELEASE_API_URL")"; then
|
|
195
|
-
echo "The configured
|
|
195
|
+
echo "The configured Senpiper Workbench release API URL is invalid." >&2
|
|
196
196
|
exit 1
|
|
197
197
|
fi
|
|
198
198
|
if [ "$DEVELOPMENT_MODE" != "1" ]; then
|
|
199
|
-
case "$RELEASE_API_ORIGIN" in https://*) ;; *) echo "The build-baked
|
|
199
|
+
case "$RELEASE_API_ORIGIN" in https://*) ;; *) echo "The build-baked Senpiper Workbench release API URL must use HTTPS." >&2; exit 1 ;; esac
|
|
200
200
|
fi
|
|
201
201
|
platform="$(detect_platform)"
|
|
202
202
|
case "$platform" in windows-*) archive_name="sp-$platform.zip" ;; *) archive_name="sp-$platform.tar.gz" ;; esac
|
|
@@ -225,7 +225,7 @@ if [ "$ALLOW_UNSIGNED" != "1" ]; then
|
|
|
225
225
|
if [ "$DEVELOPMENT_MODE" = "1" ]; then
|
|
226
226
|
echo "Set SP_RELEASE_PUBLIC_KEY for local-development verification." >&2
|
|
227
227
|
else
|
|
228
|
-
echo "This
|
|
228
|
+
echo "This Senpiper Workbench installer has no build-baked Minisign public key." >&2
|
|
229
229
|
fi
|
|
230
230
|
exit 1
|
|
231
231
|
}
|
|
@@ -273,4 +273,4 @@ old=""
|
|
|
273
273
|
switch_pointer current "releases/$release_name"
|
|
274
274
|
if [ -n "$old" ] && [ "$old" != "releases/$release_name" ]; then switch_pointer previous "$old"; fi
|
|
275
275
|
install_launcher
|
|
276
|
-
printf 'Activated
|
|
276
|
+
printf 'Activated Senpiper Workbench %s (%s)\n' "$tag" "$actual"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-manager.d.ts","sourceRoot":"","sources":["../src/release-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"release-manager.d.ts","sourceRoot":"","sources":["../src/release-manager.ts"],"names":[],"mappings":"AAuCA,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,oBAY1D","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction installerPath() {\n\tconst candidates = [\n\t\tjoin(dirname(process.execPath), \"install-sp.sh\"),\n\t\tjoin(dirname(fileURLToPath(import.meta.url)), \"install-sp.sh\"),\n\t];\n\treturn candidates.find((candidate) => existsSync(candidate));\n}\n\nasync function runInstaller(argument?: \"--repair\" | \"--rollback\") {\n\tconst installer = installerPath();\n\tif (!installer) {\n\t\tthrow new Error(\n\t\t\t\"Senpiper Workbench release installer is unavailable. Reinstall @senpiper/sp-agent from a verified release.\",\n\t\t);\n\t}\n\tconst env = { ...process.env };\n\tdelete env.SP_RELEASE_API_URL;\n\tdelete env.SP_RELEASE_PUBLIC_KEY;\n\tdelete env.SP_RELEASE_ALLOW_UNSIGNED;\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(\"sh\", argument ? [installer, argument] : [installer], { stdio: \"inherit\", env });\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Senpiper Workbench installer failed${signal ? ` with signal ${signal}` : ` with exit code ${code}`}.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\t});\n}\n\nexport async function handleSpReleaseCommand(args: string[]) {\n\tconst [command, ...rest] = args;\n\tif (command !== \"update\" && command !== \"rollback\" && command !== \"repair\") return false;\n\tif (rest.length > 0) {\n\t\tif (rest.length === 1 && (rest[0] === \"--help\" || rest[0] === \"-h\")) {\n\t\t\tconsole.log(`Usage: sp ${command}`);\n\t\t\treturn true;\n\t\t}\n\t\tthrow new Error(`Unknown ${command} option: ${rest[0]}`);\n\t}\n\tawait runInstaller(command === \"rollback\" ? \"--rollback\" : command === \"repair\" ? \"--repair\" : undefined);\n\treturn true;\n}\n"]}
|
package/dist/release-manager.js
CHANGED
|
@@ -12,7 +12,7 @@ function installerPath() {
|
|
|
12
12
|
async function runInstaller(argument) {
|
|
13
13
|
const installer = installerPath();
|
|
14
14
|
if (!installer) {
|
|
15
|
-
throw new Error("
|
|
15
|
+
throw new Error("Senpiper Workbench release installer is unavailable. Reinstall @senpiper/sp-agent from a verified release.");
|
|
16
16
|
}
|
|
17
17
|
const env = { ...process.env };
|
|
18
18
|
delete env.SP_RELEASE_API_URL;
|
|
@@ -25,7 +25,7 @@ async function runInstaller(argument) {
|
|
|
25
25
|
if (code === 0)
|
|
26
26
|
resolve();
|
|
27
27
|
else
|
|
28
|
-
reject(new Error(`
|
|
28
|
+
reject(new Error(`Senpiper Workbench installer failed${signal ? ` with signal ${signal}` : ` with exit code ${code}`}.`));
|
|
29
29
|
});
|
|
30
30
|
});
|
|
31
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-manager.js","sourceRoot":"","sources":["../src/release-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,SAAS,aAAa,GAAG;IACxB,MAAM,UAAU,GAAG;QAClB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC;KAC9D,CAAC;IACF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAAA,CAC7D;AAED,KAAK,UAAU,YAAY,CAAC,QAAoC,EAAE;IACjE,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"release-manager.js","sourceRoot":"","sources":["../src/release-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction installerPath() {\n\tconst candidates = [\n\t\tjoin(dirname(process.execPath), \"install-sp.sh\"),\n\t\tjoin(dirname(fileURLToPath(import.meta.url)), \"install-sp.sh\"),\n\t];\n\treturn candidates.find((candidate) => existsSync(candidate));\n}\n\nasync function runInstaller(argument?: \"--repair\" | \"--rollback\") {\n\tconst installer = installerPath();\n\tif (!installer) {\n\t\tthrow new Error(\n\t\t\t\"Senpiper Workbench release installer is unavailable. Reinstall @senpiper/sp-agent from a verified release.\",\n\t\t);\n\t}\n\tconst env = { ...process.env };\n\tdelete env.SP_RELEASE_API_URL;\n\tdelete env.SP_RELEASE_PUBLIC_KEY;\n\tdelete env.SP_RELEASE_ALLOW_UNSIGNED;\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(\"sh\", argument ? [installer, argument] : [installer], { stdio: \"inherit\", env });\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code, signal) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Senpiper Workbench installer failed${signal ? ` with signal ${signal}` : ` with exit code ${code}`}.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t});\n\t});\n}\n\nexport async function handleSpReleaseCommand(args: string[]) {\n\tconst [command, ...rest] = args;\n\tif (command !== \"update\" && command !== \"rollback\" && command !== \"repair\") return false;\n\tif (rest.length > 0) {\n\t\tif (rest.length === 1 && (rest[0] === \"--help\" || rest[0] === \"-h\")) {\n\t\t\tconsole.log(`Usage: sp ${command}`);\n\t\t\treturn true;\n\t\t}\n\t\tthrow new Error(`Unknown ${command} option: ${rest[0]}`);\n\t}\n\tawait runInstaller(command === \"rollback\" ? \"--rollback\" : command === \"repair\" ? \"--repair\" : undefined);\n\treturn true;\n}\n"]}
|