@qilin-agent/ptc-runtime 0.0.0-stage → 3.1.4
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/LICENSE +21 -0
- package/README.i18n.yaml +70 -0
- package/README.md +147 -2
- package/README.zh.md +148 -0
- package/lib/index.js +161 -0
- package/lib/types/index.d.ts +112 -0
- package/lib/types/types.d.ts +155 -0
- package/package.json +37 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kkutysllb
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/ptc-runtime/ptc-runtime/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: 8904d5f5d5251a83
|
|
7
|
+
zh: 69b48f289b0416f0
|
|
8
|
+
/qilin-agent-ptc-runtime:
|
|
9
|
+
en: 3502e8f89ec8d995
|
|
10
|
+
zh: f8727b8de6754479
|
|
11
|
+
/qilin-agent-ptc-runtime/summary:
|
|
12
|
+
en: aa7a516fb2d2aa4e
|
|
13
|
+
zh: 376b1643a609cfcc
|
|
14
|
+
/qilin-agent-ptc-runtime/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 09388d293f9be9cb
|
|
17
|
+
/qilin-agent-ptc-runtime/use-this-package:
|
|
18
|
+
en: d44e65c8661b730f
|
|
19
|
+
zh: 9c77a9f84eb0bbea
|
|
20
|
+
/qilin-agent-ptc-runtime/use-this-package/run-a-program:
|
|
21
|
+
en: 6f97019cebc2f417
|
|
22
|
+
zh: c56f18a690dbe814
|
|
23
|
+
/qilin-agent-ptc-runtime/use-this-package/choose-a-backend:
|
|
24
|
+
en: a5003c50fdc3d4a2
|
|
25
|
+
zh: ff515f42f2190595
|
|
26
|
+
/qilin-agent-ptc-runtime/use-this-package/name-your-bindings-portably:
|
|
27
|
+
en: 4e46c1672701b8df
|
|
28
|
+
zh: 0353c5855c9ff6be
|
|
29
|
+
/qilin-agent-ptc-runtime/use-this-package/what-can-go-wrong:
|
|
30
|
+
en: 44f9fdf2c8e2cacc
|
|
31
|
+
zh: 99dd555a49075f88
|
|
32
|
+
/qilin-agent-ptc-runtime/understand-the-implementation:
|
|
33
|
+
en: 686d570f5e669fa4
|
|
34
|
+
zh: 2075cf27c30f251a
|
|
35
|
+
/qilin-agent-ptc-runtime/understand-the-implementation/design-concept:
|
|
36
|
+
en: 431cb865534531fd
|
|
37
|
+
zh: c8657a788cd7f548
|
|
38
|
+
/qilin-agent-ptc-runtime/understand-the-implementation/service-api:
|
|
39
|
+
en: 30e9c684936d592e
|
|
40
|
+
zh: ac0a5ffc90aa39a8
|
|
41
|
+
/qilin-agent-ptc-runtime/understand-the-implementation/vocabulary:
|
|
42
|
+
en: 855cb8366e3bd293
|
|
43
|
+
zh: da6d7a0ce51f97fc
|
|
44
|
+
/qilin-agent-ptc-runtime/understand-the-implementation/portable-identifiers:
|
|
45
|
+
en: 77cb0cf02489d96e
|
|
46
|
+
zh: 7bbf502ee570911c
|
|
47
|
+
/qilin-agent-ptc-runtime/understand-the-implementation/source-map:
|
|
48
|
+
en: 85b65ceb9be0c49f
|
|
49
|
+
zh: 52df7f06d4e49d6e
|
|
50
|
+
/qilin-agent-ptc-runtime/further-exploration:
|
|
51
|
+
en: 35820f1d5fd01020
|
|
52
|
+
zh: 5cc8f5aab55bcc93
|
|
53
|
+
/qilin-agent-ptc-runtime/model-experience:
|
|
54
|
+
en: d892ff107f13572b
|
|
55
|
+
zh: 162a6d64de2eee23
|
|
56
|
+
/qilin-agent-ptc-runtime/model-experience/kv-cache-effect:
|
|
57
|
+
en: 40294c1c31b74824
|
|
58
|
+
zh: 081cebc2e2650f03
|
|
59
|
+
/qilin-agent-ptc-runtime/known-limitations-and-deferred-work:
|
|
60
|
+
en: 7f30f78c5d427667
|
|
61
|
+
zh: 99d21160016deea2
|
|
62
|
+
/qilin-agent-ptc-runtime/known-limitations-and-deferred-work/dev-note:
|
|
63
|
+
en: d56846da29ad869c
|
|
64
|
+
zh: 0397151a7e29b8ba
|
|
65
|
+
/qilin-agent-ptc-runtime/known-limitations-and-deferred-work/dev-note/future-persistent-kernel-backend:
|
|
66
|
+
en: cfefaae6ed9705d5
|
|
67
|
+
zh: 3cca5b1bd92445b0
|
|
68
|
+
/qilin-agent-ptc-runtime/known-limitations-and-deferred-work/dev-note/future-container-backend:
|
|
69
|
+
en: 2b94202842f0556c
|
|
70
|
+
zh: 5aa0311fa621a018
|
package/README.md
CHANGED
|
@@ -1,3 +1,148 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Abstract PTC execution seam (`ctx.ptcRuntime`) for users and maintainers composing, consuming, or building a backend that runs one model-written program against host-provided bindings."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @qilin-agent/ptc-runtime
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Use `qilin-ptc-runtime` to run one model-written program against host-provided asynchronous functions through a configured backend. A request returns a lossless-JSON value, ordered per-channel logs, or a structured error; program failures resolve in the result, while rejected promises indicate caller misuse. Each run is isolated from prior runs, and the runtime has no knowledge of tools or sessions. Choose an execution backend separately; its language and isolation descriptors identify the required source language and execution substrate but do not themselves promise a security boundary.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Choose this package when you compose a deployment that executes model-written programs, consume `ctx.ptcRuntime` directly, or build a backend that runs programs. PTC mode in `qilin-tools` uses it for tool programs, and `qilin-workflow-ptc` uses it for workflow orchestration. Each consumer owns the content returned to its model.
|
|
29
|
+
|
|
30
|
+
### Run a program
|
|
31
|
+
|
|
32
|
+
Give the runtime a program and binding namespaces, then call `resolve(request)` followed by `run(spec)`. Resolution validates optional cwd, timeout and sandbox policy against the provider's capabilities and fills deployment defaults. The program runs as an async function body, so top-level `await` and `return` work; a lossless-JSON completion becomes `result.value`, captured text becomes `result.logs`, and program failures become `result.error`. Each output channel preserves its own order, while cross-channel interleaving is backend-dependent.
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
const spec = ctx.ptcRuntime.resolve({
|
|
36
|
+
program: 'return await tools.add({ a: 1, b: 2 })',
|
|
37
|
+
bindings: [{ global: 'tools', functions: { add: async (args) => args.a + args.b } }],
|
|
38
|
+
})
|
|
39
|
+
const result = await ctx.ptcRuntime.run(spec)
|
|
40
|
+
// result.value === 3
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Choose a backend
|
|
44
|
+
|
|
45
|
+
Backends expose `language` and `isolation` as diagnostic descriptors; neither grants authority or proves confinement. [`qilin-ptc-runtime-node`](../ptc-runtime-node/README.md) executes erasable TypeScript in a fresh managed Node process under the resolved sandbox policy. The private [`qilin-experimental-ptc-runtime-python`](../../experimental/ptc-runtime-python/README.md) provider executes Python in a fresh CPython subprocess without file confinement. `sandboxMode` advertises a provider's deployment file-policy mode, or is absent when that capability is unsupported.
|
|
46
|
+
|
|
47
|
+
### Name your bindings portably
|
|
48
|
+
|
|
49
|
+
Binding-global and error-class names are language-portable: they must match `[A-Za-z_][A-Za-z0-9_]*`, avoid every portable target language's reserved words, and avoid backend-owned slots, so one namespace list is valid against every backend. A name like `$tools`, `lambda`, or `console` fails the run before it starts; the exact exclusion sets are part of the seam contract.
|
|
50
|
+
|
|
51
|
+
### What can go wrong
|
|
52
|
+
|
|
53
|
+
Failures arrive as `result.error` with an orthogonal `kind`: `exception`, `timeout`, `abort`, `worker-exit`, `invalid-output`, `output-limit`, `protocol` or `sandbox-unavailable`. Providers return applicable `result.sandbox` facts separately from success or failure. Invalid or unsupported execution options fail during `resolve`; `run` rejects caller misuse, such as unresolved inputs, invalid binding names or a call after disposal.
|
|
54
|
+
|
|
55
|
+
-----
|
|
56
|
+
|
|
57
|
+
<a id="understand-the-implementation"></a>
|
|
58
|
+
## Understand the implementation
|
|
59
|
+
|
|
60
|
+
<details>
|
|
61
|
+
<summary>Implementation internals — click to expand</summary>
|
|
62
|
+
|
|
63
|
+
This section explains the design behind the seam; observable behavior is fully covered in [Use this package](#use-this-package).
|
|
64
|
+
|
|
65
|
+
### Design concept
|
|
66
|
+
|
|
67
|
+
The package is the Service Definition role of the PTC execution capability seam ([capability seams](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): an abstract `PtcRuntime extends Service` registered as `ctx.ptcRuntime`, plus the vocabulary providers and consumers share. Providers subclass `PtcRuntime`, implement `resolve` and `run`, and register the service. PTC mode in `qilin-tools` owns tool bindings, while `qilin-workflow-ptc` owns workflow hooks and child agents. The runtime stays ignorant of tools and sessions by contract: it receives a program, named async bindings and resolved execution options, then returns captured output, the outcome and applicable sandbox facts.
|
|
68
|
+
|
|
69
|
+
### Service API
|
|
70
|
+
|
|
71
|
+
The readonly `timeout` descriptor exposes numeric `{ defaultMs, maxMs }` for consumer presentation; an absent descriptor means numeric overrides are unsupported. An omitted `timeoutMs` selects the provider default; a number requests a validated, capped elapsed budget; explicit `null` requests no elapsed deadline. A provider rejects choices it does not support. The Node workflow adapter requests `null`, while the model-facing `run_code` tool accepts only positive numeric overrides.
|
|
72
|
+
|
|
73
|
+
`executionInstructions` supplies provider-owned usage guidance, or an empty string when none is needed. Consumers can include it in their program presentation without identifying the provider from its language or isolation descriptor; PTC includes it in the logged `run_code` schema.
|
|
74
|
+
|
|
75
|
+
`resolve(request)` owns supported option validation and deployment defaulting. `run(spec)` executes the complete inputs and resolves program outcomes after cleanup. Language and substrate descriptors guide presentation; `sandboxMode` indicates whether the consumer can pass a resolved file policy. Neither descriptors nor a successful program result substitute for the backend's reported enforcement facts.
|
|
76
|
+
|
|
77
|
+
The exhaustive semantics live in the [PTC runtime subsystem reference](../../../docs/subsystems/ptc-runtime.md); the exact signatures are in [`src/index.ts`](src/index.ts).
|
|
78
|
+
|
|
79
|
+
### Vocabulary
|
|
80
|
+
|
|
81
|
+
`PtcRunRequest` carries the program, host bindings, cancellation and optional execution choices. `PtcRunSpec` requires the resolved cwd and an explicit numeric or null deadline choice. `PtcBindingNamespace` declares program globals and optional typed rejection constructors. `PtcRunResult` separates logs/value, failure and `PtcRunSandbox` facts; exact fields and provider obligations live in [`src/types.ts`](src/types.ts).
|
|
82
|
+
|
|
83
|
+
### Portable identifiers
|
|
84
|
+
|
|
85
|
+
Binding-global and error-class names are language-portable: they must match the identifier subset `[A-Za-z_][A-Za-z0-9_]*` (no JS-only `$`) and clear the seam-exported exclusion sets, so one `bindings` list is valid against every backend. The package exports the contract every backend enforces — `PORTABLE_RESERVED_WORDS` (ECMAScript ∪ Python reserved words), `RESERVED_BINDING_GLOBALS` (backend-owned globals such as `console` and `__qilin_main__`), `RESERVED_ERROR_MEMBERS` and `DUNDER_MEMBER` (error-member exclusions) — so a name like `$tools`, `lambda`, or `__qilin_main__` makes `run()` reject as seam misuse on any backend. See `src/index.ts` for the exact sets.
|
|
86
|
+
|
|
87
|
+
### Source map
|
|
88
|
+
|
|
89
|
+
| File | Role |
|
|
90
|
+
|---|---|
|
|
91
|
+
| [`src/index.ts`](src/index.ts) | Plugin entry: abstract `PtcRuntime` service and the portable-identifier exclusion sets |
|
|
92
|
+
| [`src/types.ts`](src/types.ts) | Vocabulary: `PtcRunRequest`, `PtcRunSpec`, bindings, results, failures and sandbox facts |
|
|
93
|
+
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
-----
|
|
97
|
+
|
|
98
|
+
<a id="further-exploration"></a>
|
|
99
|
+
## Further Exploration
|
|
100
|
+
|
|
101
|
+
Read these when the package-level contract is not enough. They move from the PTC mode consumer to the backends and the capability-seam model.
|
|
102
|
+
|
|
103
|
+
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.md) — how the tool registry consumes `ctx.ptcRuntime` and presents `run_code` to the model.
|
|
104
|
+
- [Node process backend](../ptc-runtime-node/README.md) — the shipped TypeScript execution backend.
|
|
105
|
+
- [Experimental Python backend](../../experimental/ptc-runtime-python/README.md) — the private CPython subprocess provider and its fd-3 protocol.
|
|
106
|
+
- [PTC runtime subsystem reference](../../../docs/subsystems/ptc-runtime.md) — request/result vocabulary, bindings, and the `ctx.ptcRuntime` cordis surface.
|
|
107
|
+
- [Capability seams](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) — the Service Definition / Service Provider / Consumer split.
|
|
108
|
+
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
<a id="model-experience"></a>
|
|
112
|
+
## Model Experience
|
|
113
|
+
|
|
114
|
+
Indirectly, through PTC mode in `qilin-tools` and the workflow adapter, which present program outcomes through their own tool results.
|
|
115
|
+
|
|
116
|
+
#### KV Cache effect
|
|
117
|
+
|
|
118
|
+
No direct invalidation; the named consumer owns any request-prefix changes.
|
|
119
|
+
|
|
120
|
+
## Known Limitations and Deferred Work
|
|
121
|
+
|
|
122
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
These limits define what the seam cannot do; they are current package constraints, not a task backlog.
|
|
126
|
+
|
|
127
|
+
- **`run()` is one-shot** — `logs` arrive only on the resolved `PtcRunResult`; the seam exposes no streaming-log or progress API for a live program's output.
|
|
128
|
+
- **No state survives between runs** — every request runs against a fresh world; a persistent REPL-style kernel is deferred until a backend brings its own logging story.
|
|
129
|
+
- **Providers have different confinement capabilities** — the shipped Node provider enforces a resolved file policy, while the private experimental Python provider rejects an explicit policy. No container provider is supplied.
|
|
130
|
+
- **No uniform binding byte cap applies across providers** — each provider owns its transport limits; a binding can still allocate memory before its result reaches those limits.
|
|
131
|
+
|
|
132
|
+
<a id="dev-note"></a>
|
|
133
|
+
### Dev Note
|
|
134
|
+
|
|
135
|
+
<details>
|
|
136
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
137
|
+
|
|
138
|
+
This Dev Note is working context for maintainers: undecided directions and open questions. It is explicitly non-authoritative — shipped behavior and limits live in the sections above and the package code.
|
|
139
|
+
|
|
140
|
+
#### Future: persistent kernel backend
|
|
141
|
+
|
|
142
|
+
A REPL-style kernel that keeps state across `run_code` calls remains undecided; it would need its own logging story, because the no-state-between-runs contract is what keeps every request reconstructable from the session log alone.
|
|
143
|
+
|
|
144
|
+
#### Future: container backend
|
|
145
|
+
|
|
146
|
+
A container-class backend would provide a hard multi-tenant boundary for both code and shell execution; nothing is decided beyond the well-known `isolation` value.
|
|
147
|
+
|
|
148
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "抽象 PTC 执行 seam(`ctx.ptcRuntime`),供用户与维护者组合、消费或构建后端,以针对宿主提供的绑定运行一段模型编写的程序。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @qilin-agent/ptc-runtime
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
使用 `qilin-ptc-runtime`,可通过已配置的后端,针对宿主提供的异步函数运行一段模型编写的程序。请求返回无损 JSON 值、通道内有序的日志或结构化错误;程序失败在结果中 resolve,而 Promise reject 表示调用方误用。每次运行都与先前运行隔离,且运行时不了解工具或会话。执行后端需另行选择;其语言与隔离描述符标明所需的源语言和执行基底,但这些描述符本身不承诺安全边界。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
当你要组合一个执行模型程序的部署、直接消费 `ctx.ptcRuntime`,或构建运行程序的后端时,选择本包。`qilin-tools` 中的 PTC mode 用它执行工具程序,`qilin-workflow-ptc` 用它编排工作流。每个消费方负责返回给模型的内容。
|
|
29
|
+
|
|
30
|
+
### 运行一个程序
|
|
31
|
+
|
|
32
|
+
向运行时提供程序与绑定命名空间,然后依次调用 `resolve(request)` 和 `run(spec)`。解析根据提供方能力验证可选 cwd、timeout 与沙箱策略,并填入部署默认值。程序作为异步函数体运行,支持顶层 `await` 与 `return`;无损 JSON 完成值成为 `result.value`,捕获文本成为 `result.logs`,程序失败成为 `result.error`。每个输出通道保持自身顺序,跨通道交错由后端决定。
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
const spec = ctx.ptcRuntime.resolve({
|
|
36
|
+
program: 'return await tools.add({ a: 1, b: 2 })',
|
|
37
|
+
bindings: [{ global: 'tools', functions: { add: async (args) => args.a + args.b } }],
|
|
38
|
+
})
|
|
39
|
+
const result = await ctx.ptcRuntime.run(spec)
|
|
40
|
+
// result.value === 3
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 选择后端
|
|
44
|
+
|
|
45
|
+
后端以 `language` 与 `isolation` 提供诊断描述符;两者都不授予权限或证明约束。[`qilin-ptc-runtime-node`](../ptc-runtime-node/README.zh.md) 在全新的受管 Node 进程中按已解析沙箱策略执行可擦除 TypeScript。私有的 [`qilin-experimental-ptc-runtime-python`](../../experimental/ptc-runtime-python/README.zh.md) 提供方在全新 CPython 子进程中执行 Python,不提供文件约束。`sandboxMode` 声明提供方的部署文件策略模式;不支持该能力时则缺省。
|
|
46
|
+
|
|
47
|
+
### 可移植地命名绑定
|
|
48
|
+
|
|
49
|
+
binding-global 与 error-class 名称是语言可移植的:必须匹配 `[A-Za-z_][A-Za-z0-9_]*`,避开每个可移植目标语言的保留字,并避开后端拥有的槽位,因此同一份命名空间列表对每个后端都有效。`$tools`、`lambda` 或 `console` 之类的名称会在运行开始前失败;确切的排除集是 seam 约定的一部分。
|
|
50
|
+
|
|
51
|
+
### 可能出什么问题
|
|
52
|
+
|
|
53
|
+
失败以 `result.error` 返回,带正交的 `kind`:`exception`、`timeout`、`abort`、`worker-exit`、`invalid-output`、`output-limit`、`protocol` 或 `sandbox-unavailable`。提供方在成功或失败之外,单独返回适用的 `result.sandbox` 事实。无效或不支持的执行选项在 `resolve` 期间失败;`run` 拒绝调用方误用,例如未解析输入、无效绑定名或资源释放后的调用。
|
|
54
|
+
|
|
55
|
+
-----
|
|
56
|
+
|
|
57
|
+
<a id="understand-the-implementation"></a>
|
|
58
|
+
## 理解实现
|
|
59
|
+
|
|
60
|
+
<details>
|
|
61
|
+
<summary>实现细节——点击展开</summary>
|
|
62
|
+
|
|
63
|
+
本节解释 seam 背后的设计;可观察行为已在[使用本包](#use-this-package)中完整说明。
|
|
64
|
+
|
|
65
|
+
### 设计理念
|
|
66
|
+
|
|
67
|
+
本包是 PTC 执行能力 seam 的 Service Definition 角色([能力 seam](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md)):一个注册为 `ctx.ptcRuntime` 的抽象 `PtcRuntime extends Service`,加上提供方与消费方共享的词汇。提供方继承 `PtcRuntime`、实现 `resolve` 和 `run` 并注册服务。`qilin-tools` 中的 PTC mode 负责工具绑定,`qilin-workflow-ptc` 负责工作流钩子与子 agent。按约定,运行时不了解工具与会话:它接收程序、具名异步绑定和已解析执行选项,然后返回捕获输出、执行结果与适用的沙箱事实。
|
|
68
|
+
|
|
69
|
+
### 服务 API
|
|
70
|
+
|
|
71
|
+
只读 `timeout` 描述符公开数值型 `{ defaultMs, maxMs }`,供消费方呈现;描述符缺省表示不支持数值覆盖。省略 `timeoutMs` 使用提供方默认值;数值请求经过验证和封顶的经过时间预算;显式 `null` 请求不设经过时间截止。提供方拒绝不支持的选择。Node 工作流适配器请求 `null`,而面向模型的 `run_code` 工具只接受正数覆盖值。
|
|
72
|
+
|
|
73
|
+
`executionInstructions` 提供由运行时拥有的使用说明;不需要说明时返回空字符串。消费方可将其纳入程序呈现,无需根据语言或隔离描述符识别提供方;PTC 将它纳入已记录的 `run_code` schema。
|
|
74
|
+
|
|
75
|
+
`resolve(request)` 负责支持选项的验证与部署默认值。`run(spec)` 执行完整输入,并在清理后返回程序结果。语言和执行基底描述符指导呈现;`sandboxMode` 表示消费方能否传入已解析文件策略。描述符与程序成功结果都不能代替后端报告的强制能力事实。
|
|
76
|
+
|
|
77
|
+
穷尽式语义见[PTC 运行时子系统参考](../../../docs/subsystems/ptc-runtime.zh.md);确切签名见 [`src/index.ts`](src/index.ts)。
|
|
78
|
+
|
|
79
|
+
### 词汇
|
|
80
|
+
|
|
81
|
+
`PtcRunRequest` 携带程序、Host 绑定、取消和可选执行选择。`PtcRunSpec` 要求已解析的 cwd 和明确的数值或 null 截止选择。`PtcBindingNamespace` 声明程序全局对象与可选的类型化拒绝构造器。`PtcRunResult` 将日志/值、失败与 `PtcRunSandbox` 事实分开;确切字段与提供方义务见 [`src/types.ts`](src/types.ts)。
|
|
82
|
+
|
|
83
|
+
### 可移植标识符
|
|
84
|
+
|
|
85
|
+
binding-global 与 error-class 名称是语言可移植的:必须匹配标识符子集 `[A-Za-z_][A-Za-z0-9_]*`(不含 JS 专有的 `$`)并通过 seam 导出的排除集,因此同一份 `bindings` 列表对每个后端都有效。本包导出每个后端都执行的约定——`PORTABLE_RESERVED_WORDS`(ECMAScript ∪ Python 保留字)、`RESERVED_BINDING_GLOBALS`(如 `console`、`__qilin_main__` 等后端拥有的 global)、`RESERVED_ERROR_MEMBERS` 与 `DUNDER_MEMBER`(error-member 排除)——因此 `$tools`、`lambda` 或 `__qilin_main__` 之类的名称会让 `run()` 在任何后端上作为 seam 误用而 reject。确切集合见 `src/index.ts`。
|
|
86
|
+
|
|
87
|
+
### 源码地图
|
|
88
|
+
|
|
89
|
+
| 文件 | 职责 |
|
|
90
|
+
|---|---|
|
|
91
|
+
| [`src/index.ts`](src/index.ts) | 插件入口:抽象 `PtcRuntime` 服务与可移植标识符排除集 |
|
|
92
|
+
| [`src/types.ts`](src/types.ts) | 词汇:`PtcRunRequest`、`PtcRunSpec`、绑定、结果、失败与沙箱事实 |
|
|
93
|
+
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
-----
|
|
97
|
+
|
|
98
|
+
<a id="further-exploration"></a>
|
|
99
|
+
## 进一步探索
|
|
100
|
+
|
|
101
|
+
当包级约定不够用时阅读以下内容。它们从 PTC mode 消费方进入后端与能力 seam 模型。
|
|
102
|
+
|
|
103
|
+
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.zh.md)——工具注册表如何消费 `ctx.ptcRuntime` 并把 `run_code` 呈现给模型。
|
|
104
|
+
- [Node 进程后端](../ptc-runtime-node/README.zh.md)——已发布的 TypeScript 执行后端。
|
|
105
|
+
- [实验性 Python 后端](../../experimental/ptc-runtime-python/README.zh.md)——私有的 CPython 子进程提供方及其 fd-3 协议。
|
|
106
|
+
- [PTC 运行时子系统参考](../../../docs/subsystems/ptc-runtime.zh.md)——请求/结果词汇、绑定与 `ctx.ptcRuntime` 的 cordis 接口面。
|
|
107
|
+
- [能力 seam](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md)——Service Definition / Service Provider / Consumer 拆分。
|
|
108
|
+
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
<a id="model-experience"></a>
|
|
112
|
+
## 模型体验
|
|
113
|
+
|
|
114
|
+
通过 `qilin-tools` 中的 PTC mode 与工作流适配器间接提供;它们通过各自的工具结果呈现程序结果。
|
|
115
|
+
|
|
116
|
+
#### KV Cache 影响
|
|
117
|
+
|
|
118
|
+
不会直接失效;由上述消费方负责请求前缀变更。
|
|
119
|
+
|
|
120
|
+
## 已知限制与延期工作
|
|
121
|
+
|
|
122
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
这些限制说明 seam 不能做什么;它们是当前包约束,不是任务积压。
|
|
126
|
+
|
|
127
|
+
- **`run()` 是一次性的**——`logs` 只有在 `PtcRunResult` resolve 后才能获得;seam 不提供正在运行的程序所产生输出的流式日志或进度接口。
|
|
128
|
+
- **运行之间不保留状态**——每次请求都在全新环境中运行;持久 REPL 风格内核在某个后端带来自己的日志方案之前保持延期。
|
|
129
|
+
- **提供方的约束能力不同**——已发布 Node 提供方强制执行已解析文件策略,私有实验性 Python 提供方拒绝显式策略。不提供容器提供方。
|
|
130
|
+
- **提供方之间没有统一的绑定字节上限**——各提供方负责自己的传输限制;绑定仍可能在结果到达这些限制前分配内存。
|
|
131
|
+
|
|
132
|
+
<a id="dev-note"></a>
|
|
133
|
+
### 开发备注
|
|
134
|
+
|
|
135
|
+
<details>
|
|
136
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
137
|
+
|
|
138
|
+
本开发备注是维护者的工作上下文:尚未决定的方向与开放问题。它明确不具权威性——已交付的行为与限制以上文和包代码为准。
|
|
139
|
+
|
|
140
|
+
#### 未来:持久内核后端
|
|
141
|
+
|
|
142
|
+
跨 `run_code` 调用保留状态的 REPL 风格内核仍未决定;它需要自己的日志方案,因为「运行之间不保留状态」的约定正是让每次请求仅凭会话日志即可重建的原因。
|
|
143
|
+
|
|
144
|
+
#### 未来:容器后端
|
|
145
|
+
|
|
146
|
+
容器级后端将为代码与 shell 执行都提供硬性的多租户边界;除已知的 `isolation` 值外,暂无任何决定。
|
|
147
|
+
|
|
148
|
+
</details>
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Service } from "@qilin-agent/kylin";
|
|
2
|
+
//#region lib/types/index.js
|
|
3
|
+
/**
|
|
4
|
+
* Service Definition for the PTC execution capability seam that runs one model-written program against host async bindings.
|
|
5
|
+
* Runtimes know nothing about tools or sessions; consumers own those concerns.
|
|
6
|
+
* @module @qilin-agent/ptc-runtime
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Binding globals EVERY backend refuses because SOME backend owns the slot in
|
|
10
|
+
* the program's namespace: `console` (Node's log capture), and
|
|
11
|
+
* `__qilin_main__`/`__builtins__`/`__name__` (the Python backend's bootstrap
|
|
12
|
+
* wrapper and seeded module globals),
|
|
13
|
+
* and `__debug__`. One shared set — rather than each backend refusing only its
|
|
14
|
+
* own slots — keeps the portability promise real: a namespace list valid on
|
|
15
|
+
* one backend is valid on all, so a caller cannot pick a name that works on
|
|
16
|
+
* Node and collides on Python (or vice versa). `__name__` et al. ARE
|
|
17
|
+
* valid portable identifiers, so the identifier rule on
|
|
18
|
+
* `PtcBindingNamespace.global` never rejects them — hence this explicit set.
|
|
19
|
+
* (Error members differ: {@link DUNDER_MEMBER} refuses every dunder form
|
|
20
|
+
* wholesale; binding globals refuse only the names listed here.) `__debug__`
|
|
21
|
+
* is listed for a different reason than a collision: CPython compiles a bare
|
|
22
|
+
* `__debug__` reference to the constant `True` and rejects any assignment to
|
|
23
|
+
* the name at COMPILE time, so an injected global under that name is
|
|
24
|
+
* unreachable from the program — accepted by validation, unusable on the
|
|
25
|
+
* Python backend, which is exactly the split the shared set exists to prevent.
|
|
26
|
+
*/
|
|
27
|
+
const RESERVED_BINDING_GLOBALS = new Set([
|
|
28
|
+
"console",
|
|
29
|
+
"__qilin_main__",
|
|
30
|
+
"__builtins__",
|
|
31
|
+
"__name__",
|
|
32
|
+
"__debug__"
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* `PtcBindingErrorClass.memberNameProperty` names EVERY backend refuses, as
|
|
36
|
+
* one shared contract so a request valid on one backend is valid on all. The
|
|
37
|
+
* JS `Error` exclusions (`name`, `message`, `stack`) and Python's
|
|
38
|
+
* exception-protocol members (`args`, `with_traceback`, `add_note`) are
|
|
39
|
+
* listed by name; dunder-form names (`__x__`, non-empty middle) are refused
|
|
40
|
+
* wholesale — several are constrained CPython descriptors whose `setattr`
|
|
41
|
+
* raises while constructing the rejection, and the exact set is an interpreter
|
|
42
|
+
* version detail. Any other non-empty own property name is accepted everywhere.
|
|
43
|
+
*/
|
|
44
|
+
const RESERVED_ERROR_MEMBERS = new Set([
|
|
45
|
+
"name",
|
|
46
|
+
"message",
|
|
47
|
+
"stack",
|
|
48
|
+
"args",
|
|
49
|
+
"with_traceback",
|
|
50
|
+
"add_note"
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* Dunder form (`__x__`, non-empty middle): object-protocol slots in Python,
|
|
54
|
+
* refused as {@link RESERVED_ERROR_MEMBERS | error members} on every backend.
|
|
55
|
+
*/
|
|
56
|
+
const DUNDER_MEMBER = /^__.+__$/;
|
|
57
|
+
/**
|
|
58
|
+
* Reserved words of every portable target language (ECMAScript ∪ Python),
|
|
59
|
+
* refused as {@link PtcBindingNamespace.global} / error-class names by all
|
|
60
|
+
* backends, one per language: the released TypeScript Node process and the
|
|
61
|
+
* experimental, private CPython subprocess. The portable-identifier contract
|
|
62
|
+
* promises a namespace list valid on one backend is valid on every backend; a
|
|
63
|
+
* per-language check would let `lambda` pass the TypeScript backend and fail
|
|
64
|
+
* the Python one. Extending the seam with a new language means widening this
|
|
65
|
+
* union (a breaking review of existing binding names, by design).
|
|
66
|
+
*/
|
|
67
|
+
const PORTABLE_RESERVED_WORDS = new Set([
|
|
68
|
+
"await",
|
|
69
|
+
"break",
|
|
70
|
+
"case",
|
|
71
|
+
"catch",
|
|
72
|
+
"class",
|
|
73
|
+
"const",
|
|
74
|
+
"continue",
|
|
75
|
+
"debugger",
|
|
76
|
+
"default",
|
|
77
|
+
"delete",
|
|
78
|
+
"do",
|
|
79
|
+
"else",
|
|
80
|
+
"enum",
|
|
81
|
+
"export",
|
|
82
|
+
"extends",
|
|
83
|
+
"false",
|
|
84
|
+
"finally",
|
|
85
|
+
"for",
|
|
86
|
+
"function",
|
|
87
|
+
"if",
|
|
88
|
+
"import",
|
|
89
|
+
"in",
|
|
90
|
+
"instanceof",
|
|
91
|
+
"new",
|
|
92
|
+
"null",
|
|
93
|
+
"return",
|
|
94
|
+
"super",
|
|
95
|
+
"switch",
|
|
96
|
+
"this",
|
|
97
|
+
"throw",
|
|
98
|
+
"true",
|
|
99
|
+
"try",
|
|
100
|
+
"typeof",
|
|
101
|
+
"var",
|
|
102
|
+
"void",
|
|
103
|
+
"while",
|
|
104
|
+
"with",
|
|
105
|
+
"yield",
|
|
106
|
+
"let",
|
|
107
|
+
"static",
|
|
108
|
+
"implements",
|
|
109
|
+
"interface",
|
|
110
|
+
"package",
|
|
111
|
+
"private",
|
|
112
|
+
"protected",
|
|
113
|
+
"public",
|
|
114
|
+
"arguments",
|
|
115
|
+
"eval",
|
|
116
|
+
"False",
|
|
117
|
+
"None",
|
|
118
|
+
"True",
|
|
119
|
+
"and",
|
|
120
|
+
"as",
|
|
121
|
+
"assert",
|
|
122
|
+
"async",
|
|
123
|
+
"def",
|
|
124
|
+
"del",
|
|
125
|
+
"elif",
|
|
126
|
+
"except",
|
|
127
|
+
"from",
|
|
128
|
+
"global",
|
|
129
|
+
"is",
|
|
130
|
+
"lambda",
|
|
131
|
+
"nonlocal",
|
|
132
|
+
"not",
|
|
133
|
+
"or",
|
|
134
|
+
"pass",
|
|
135
|
+
"raise",
|
|
136
|
+
"match",
|
|
137
|
+
"type",
|
|
138
|
+
"_"
|
|
139
|
+
]);
|
|
140
|
+
/**
|
|
141
|
+
* Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and substrate
|
|
142
|
+
* failures resolve in {@link PtcRunResult}; only Service Definition contract misuse rejects. Implementations bridge
|
|
143
|
+
* structured-cloneable bindings, materialize each declared namespace rejection
|
|
144
|
+
* class, treat programs as hostile peers, isolate runs from one another, and
|
|
145
|
+
* terminate and await in-flight runs during disposal.
|
|
146
|
+
*/
|
|
147
|
+
var PtcRuntime = class extends Service {
|
|
148
|
+
/** Provider-owned program usage guidance for consumers to present alongside the source language. */
|
|
149
|
+
get executionInstructions() {
|
|
150
|
+
return "";
|
|
151
|
+
}
|
|
152
|
+
/** Deployment file-policy mode, or undefined for a provider without confinement support. */
|
|
153
|
+
get sandboxMode() {}
|
|
154
|
+
/** Configured numeric elapsed-time defaults and cap, or undefined when per-call overrides are unsupported. */
|
|
155
|
+
get timeout() {}
|
|
156
|
+
constructor(ctx) {
|
|
157
|
+
super(ctx, "ptcRuntime");
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
export { DUNDER_MEMBER, PORTABLE_RESERVED_WORDS, PtcRuntime, PtcRuntime as default, RESERVED_BINDING_GLOBALS, RESERVED_ERROR_MEMBERS };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Definition for the PTC execution capability seam that runs one model-written program against host async bindings.
|
|
3
|
+
* Runtimes know nothing about tools or sessions; consumers own those concerns.
|
|
4
|
+
* @module @qilin-agent/ptc-runtime
|
|
5
|
+
*/
|
|
6
|
+
import { Context, Service } from '@qilin-agent/kylin';
|
|
7
|
+
import type { PtcRunRequest, PtcRunResult, PtcRunSpec } from './types.ts';
|
|
8
|
+
import type { SandboxMode } from '@qilin-agent/sandbox';
|
|
9
|
+
export type { PtcBindingErrorClass, PtcBindingFunction, PtcBindingNamespace, PtcJsonValue, PtcRunFailure, PtcRunRequest, PtcRunResult, PtcRunSpec, PtcRunSandbox, } from './types.ts';
|
|
10
|
+
/**
|
|
11
|
+
* Binding globals EVERY backend refuses because SOME backend owns the slot in
|
|
12
|
+
* the program's namespace: `console` (Node's log capture), and
|
|
13
|
+
* `__qilin_main__`/`__builtins__`/`__name__` (the Python backend's bootstrap
|
|
14
|
+
* wrapper and seeded module globals),
|
|
15
|
+
* and `__debug__`. One shared set — rather than each backend refusing only its
|
|
16
|
+
* own slots — keeps the portability promise real: a namespace list valid on
|
|
17
|
+
* one backend is valid on all, so a caller cannot pick a name that works on
|
|
18
|
+
* Node and collides on Python (or vice versa). `__name__` et al. ARE
|
|
19
|
+
* valid portable identifiers, so the identifier rule on
|
|
20
|
+
* `PtcBindingNamespace.global` never rejects them — hence this explicit set.
|
|
21
|
+
* (Error members differ: {@link DUNDER_MEMBER} refuses every dunder form
|
|
22
|
+
* wholesale; binding globals refuse only the names listed here.) `__debug__`
|
|
23
|
+
* is listed for a different reason than a collision: CPython compiles a bare
|
|
24
|
+
* `__debug__` reference to the constant `True` and rejects any assignment to
|
|
25
|
+
* the name at COMPILE time, so an injected global under that name is
|
|
26
|
+
* unreachable from the program — accepted by validation, unusable on the
|
|
27
|
+
* Python backend, which is exactly the split the shared set exists to prevent.
|
|
28
|
+
*/
|
|
29
|
+
export declare const RESERVED_BINDING_GLOBALS: ReadonlySet<string>;
|
|
30
|
+
/**
|
|
31
|
+
* `PtcBindingErrorClass.memberNameProperty` names EVERY backend refuses, as
|
|
32
|
+
* one shared contract so a request valid on one backend is valid on all. The
|
|
33
|
+
* JS `Error` exclusions (`name`, `message`, `stack`) and Python's
|
|
34
|
+
* exception-protocol members (`args`, `with_traceback`, `add_note`) are
|
|
35
|
+
* listed by name; dunder-form names (`__x__`, non-empty middle) are refused
|
|
36
|
+
* wholesale — several are constrained CPython descriptors whose `setattr`
|
|
37
|
+
* raises while constructing the rejection, and the exact set is an interpreter
|
|
38
|
+
* version detail. Any other non-empty own property name is accepted everywhere.
|
|
39
|
+
*/
|
|
40
|
+
export declare const RESERVED_ERROR_MEMBERS: ReadonlySet<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Dunder form (`__x__`, non-empty middle): object-protocol slots in Python,
|
|
43
|
+
* refused as {@link RESERVED_ERROR_MEMBERS | error members} on every backend.
|
|
44
|
+
*/
|
|
45
|
+
export declare const DUNDER_MEMBER: RegExp;
|
|
46
|
+
/**
|
|
47
|
+
* Reserved words of every portable target language (ECMAScript ∪ Python),
|
|
48
|
+
* refused as {@link PtcBindingNamespace.global} / error-class names by all
|
|
49
|
+
* backends, one per language: the released TypeScript Node process and the
|
|
50
|
+
* experimental, private CPython subprocess. The portable-identifier contract
|
|
51
|
+
* promises a namespace list valid on one backend is valid on every backend; a
|
|
52
|
+
* per-language check would let `lambda` pass the TypeScript backend and fail
|
|
53
|
+
* the Python one. Extending the seam with a new language means widening this
|
|
54
|
+
* union (a breaking review of existing binding names, by design).
|
|
55
|
+
*/
|
|
56
|
+
export declare const PORTABLE_RESERVED_WORDS: ReadonlySet<string>;
|
|
57
|
+
declare module '@qilin-agent/kylin' {
|
|
58
|
+
interface Context {
|
|
59
|
+
ptcRuntime: PtcRuntime;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and substrate
|
|
64
|
+
* failures resolve in {@link PtcRunResult}; only Service Definition contract misuse rejects. Implementations bridge
|
|
65
|
+
* structured-cloneable bindings, materialize each declared namespace rejection
|
|
66
|
+
* class, treat programs as hostile peers, isolate runs from one another, and
|
|
67
|
+
* terminate and await in-flight runs during disposal.
|
|
68
|
+
*/
|
|
69
|
+
export declare abstract class PtcRuntime extends Service {
|
|
70
|
+
/**
|
|
71
|
+
* The source language {@link run} expects `program` to be written in, as a
|
|
72
|
+
* lowercase identifier. Informational, not gating — a consumer that
|
|
73
|
+
* generates language-specific presentation (typed SDK stubs, usage
|
|
74
|
+
* instructions) switches on it and fails loud on a language it cannot
|
|
75
|
+
* present. Well-known values: `'typescript'` and `'python'`, those
|
|
76
|
+
* `qilin-tools` presents; the TypeScript backend is released, the Python
|
|
77
|
+
* backend is experimental and private (not published).
|
|
78
|
+
*/
|
|
79
|
+
abstract readonly language: string;
|
|
80
|
+
/**
|
|
81
|
+
* The execution substrate, as a lowercase identifier. Informational, not
|
|
82
|
+
* gating — a descriptor so deployments and diagnostics can tell backends
|
|
83
|
+
* apart, not a security claim. Well-known values: `'worker-thread'`,
|
|
84
|
+
* `'process'`, `'container'`.
|
|
85
|
+
*/
|
|
86
|
+
abstract readonly isolation: string;
|
|
87
|
+
/** Provider-owned program usage guidance for consumers to present alongside the source language. */
|
|
88
|
+
get executionInstructions(): string;
|
|
89
|
+
/** Deployment file-policy mode, or undefined for a provider without confinement support. */
|
|
90
|
+
get sandboxMode(): SandboxMode | undefined;
|
|
91
|
+
/** Configured numeric elapsed-time defaults and cap, or undefined when per-call overrides are unsupported. */
|
|
92
|
+
get timeout(): {
|
|
93
|
+
defaultMs: number;
|
|
94
|
+
maxMs: number;
|
|
95
|
+
} | undefined;
|
|
96
|
+
constructor(ctx: Context);
|
|
97
|
+
/**
|
|
98
|
+
* Resolve supported options and provider defaults before execution.
|
|
99
|
+
* @param request - Program, bindings, cancellation and optional execution choices.
|
|
100
|
+
* @returns Complete directory, deadline and supported authority for run.
|
|
101
|
+
* @throws When an explicit choice is invalid or unsupported by this provider.
|
|
102
|
+
*/
|
|
103
|
+
abstract resolve(request: PtcRunRequest): PtcRunSpec;
|
|
104
|
+
/**
|
|
105
|
+
* Execute resolved inputs; program outcomes resolve as result fields.
|
|
106
|
+
* @param spec - directory, deadline, program, bindings, cancellation and supported policy.
|
|
107
|
+
* @returns Captured output and the execution outcome.
|
|
108
|
+
*/
|
|
109
|
+
abstract run(spec: PtcRunSpec): Promise<PtcRunResult>;
|
|
110
|
+
}
|
|
111
|
+
export default PtcRuntime;
|
|
112
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vocabulary types for the PTC execution seam: what a caller hands a
|
|
3
|
+
* {@link ../index.ts | PtcRuntime} and what it gets back. Pure types — no
|
|
4
|
+
* runtime code lives here.
|
|
5
|
+
*
|
|
6
|
+
* @module @qilin-agent/ptc-runtime/src/types
|
|
7
|
+
*/
|
|
8
|
+
import type { SandboxEnforcement, SandboxExecutionPolicy, SandboxMode } from '@qilin-agent/sandbox';
|
|
9
|
+
/**
|
|
10
|
+
* One host-side function exposed to the program as an async callable. The
|
|
11
|
+
* runtime bridges calls to it (possibly across a serialization boundary), so
|
|
12
|
+
* `args` and the resolution value MUST be lossless JSON. A runtime rejects a
|
|
13
|
+
* lossy or non-cloneable value with a descriptive error rather than corrupting
|
|
14
|
+
* the run. No seam-level byte cap applies to a binding resolution. A rejection
|
|
15
|
+
* of this function surfaces inside the program as a rejection of the
|
|
16
|
+
* corresponding call.
|
|
17
|
+
*/
|
|
18
|
+
export type PtcBindingFunction = (args: unknown) => Promise<PtcJsonValue>;
|
|
19
|
+
/** A lossless JSON value transferable through the dependency-light Service Definition. */
|
|
20
|
+
export type PtcJsonValue = null | boolean | number | string | PtcJsonValue[] | {
|
|
21
|
+
[key: string]: PtcJsonValue;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Program-visible typed rejection for one binding namespace. The runtime
|
|
25
|
+
* injects a real error constructor under `name`; rejected member calls become
|
|
26
|
+
* its instances and expose the exact member name through
|
|
27
|
+
* `memberNameProperty`. Both strings are runtime data rather than knowledge
|
|
28
|
+
* of a particular consumer such as PTC mode.
|
|
29
|
+
*/
|
|
30
|
+
export interface PtcBindingErrorClass {
|
|
31
|
+
/** Constructor global and resulting `Error.name`; same portable identifier rule as {@link PtcBindingNamespace.global}. */
|
|
32
|
+
name: string;
|
|
33
|
+
/**
|
|
34
|
+
* Non-empty own property for the member name. The portable exclusion set is
|
|
35
|
+
* `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__x__`, non-empty
|
|
36
|
+
* middle), enforced identically by every backend; any other name —
|
|
37
|
+
* identifiers or not — is accepted everywhere.
|
|
38
|
+
*/
|
|
39
|
+
memberNameProperty: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A named group of {@link PtcBindingFunction}s the runtime exposes to the
|
|
43
|
+
* program as one global object (e.g. `tools`). Function names are arbitrary
|
|
44
|
+
* strings — a runtime must treat names like `__proto__` or `constructor` as
|
|
45
|
+
* ordinary own properties (null-prototype construction), never as prototype
|
|
46
|
+
* collisions.
|
|
47
|
+
*/
|
|
48
|
+
export interface PtcBindingNamespace {
|
|
49
|
+
/**
|
|
50
|
+
* The global identifier the program sees. Must match the LANGUAGE-PORTABLE
|
|
51
|
+
* identifier subset `[A-Za-z_][A-Za-z0-9_]*` and no language's reserved
|
|
52
|
+
* words, so the same namespace list works against every backend regardless
|
|
53
|
+
* of `language` — a JS-only spelling like `$tools` is rejected by design,
|
|
54
|
+
* not just by the Python backend. Names that satisfy the identifier rule but
|
|
55
|
+
* name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `console`,
|
|
56
|
+
* `__qilin_main__`) are also refused everywhere; see its declaration for the
|
|
57
|
+
* exact set and why each entry is reserved.
|
|
58
|
+
*/
|
|
59
|
+
global: string;
|
|
60
|
+
/** The callable members, keyed by the exact name the program calls. */
|
|
61
|
+
functions: Record<string, PtcBindingFunction>;
|
|
62
|
+
/** Optional program-visible typed rejection contract for this namespace. */
|
|
63
|
+
errorClass?: PtcBindingErrorClass;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Caller inputs for one program. The provider's resolve method validates supported
|
|
67
|
+
* options and supplies directory, deadline, and authority before execution.
|
|
68
|
+
*/
|
|
69
|
+
export interface PtcRunRequest {
|
|
70
|
+
/**
|
|
71
|
+
* The program source, in the runtime's {@link ../index.ts | language}. It
|
|
72
|
+
* runs as the body of an async function: top-level `await` and `return`
|
|
73
|
+
* are available, and the completion value becomes
|
|
74
|
+
* {@link PtcRunResult.value}.
|
|
75
|
+
*/
|
|
76
|
+
program: string;
|
|
77
|
+
/** Host functions exposed to the program, one global object per namespace. */
|
|
78
|
+
bindings: PtcBindingNamespace[];
|
|
79
|
+
/** Working directory in the mounted filesystem and subprocess execution world. */
|
|
80
|
+
cwd?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Elapsed execution budget in milliseconds. Omission uses provider defaults;
|
|
83
|
+
* null requests no deadline. Providers validate and cap numeric budgets or reject unsupported choices.
|
|
84
|
+
*/
|
|
85
|
+
timeoutMs?: number | null;
|
|
86
|
+
/** Resolved authority for this execution. Providers without confinement reject an explicit policy. */
|
|
87
|
+
sandboxPolicy?: SandboxExecutionPolicy;
|
|
88
|
+
/**
|
|
89
|
+
* Abort the run: the runtime stops the program (hard, even mid-loop) and
|
|
90
|
+
* resolves with a {@link PtcRunFailure} of kind `'abort'`. In-flight
|
|
91
|
+
* binding calls are the CALLER's to settle — the runtime only stops asking.
|
|
92
|
+
*/
|
|
93
|
+
signal?: AbortSignal;
|
|
94
|
+
}
|
|
95
|
+
/** Fully resolved execution inputs; run never supplies a missing directory or deadline choice. */
|
|
96
|
+
export interface PtcRunSpec extends PtcRunRequest {
|
|
97
|
+
/** Absolute directory in the provider's execution world. */
|
|
98
|
+
cwd: string;
|
|
99
|
+
/** Positive finite elapsed budget in milliseconds after provider capping, or null for no deadline. */
|
|
100
|
+
timeoutMs: number | null;
|
|
101
|
+
}
|
|
102
|
+
/** File confinement applied to a program, independently of its terminal outcome. */
|
|
103
|
+
export interface PtcRunSandbox {
|
|
104
|
+
/** File-effect mode used for this execution. */
|
|
105
|
+
mode: SandboxMode;
|
|
106
|
+
/** Program failure text matched backend diagnostics; not enforcement proof or an exhaustive denial record. */
|
|
107
|
+
denied: boolean;
|
|
108
|
+
/** Completeness reported by the selected confining backend; absent for full access. */
|
|
109
|
+
enforcement?: SandboxEnforcement;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Why a run failed. The kinds are orthogonal outcomes reported independently
|
|
113
|
+
* (per docs/defensive-patterns.md): a budget expiry is not an exception, an
|
|
114
|
+
* abort is not a timeout, and a substrate death is neither.
|
|
115
|
+
*
|
|
116
|
+
* - `'exception'` — the program threw or failed to parse/transform.
|
|
117
|
+
* - `'timeout'` — an implementation-owned budget expired; the message says which.
|
|
118
|
+
* - `'abort'` — {@link PtcRunRequest.signal} fired.
|
|
119
|
+
* - `'worker-exit'` — the execution substrate died without settling (e.g. OOM).
|
|
120
|
+
* - `'invalid-output'` — the completion value was not lossless JSON.
|
|
121
|
+
* - `'output-limit'` — the serialized outer logs/value/diagnostic exceeded the configured cap.
|
|
122
|
+
* - `'protocol'` — the program sent invalid or over-budget control traffic.
|
|
123
|
+
* - `'sandbox-unavailable'` — required confinement could not be established.
|
|
124
|
+
*/
|
|
125
|
+
export interface PtcRunFailure {
|
|
126
|
+
/** The failure class (see the interface doc for each kind's meaning). */
|
|
127
|
+
kind: 'exception' | 'timeout' | 'abort' | 'worker-exit' | 'invalid-output' | 'output-limit' | 'protocol' | 'sandbox-unavailable';
|
|
128
|
+
/** Human-readable detail, suitable for feeding back to a model to self-correct. */
|
|
129
|
+
message: string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The outcome of one run. An error is a FIELD on a resolved result, never a
|
|
133
|
+
* rejection of `run()` — reporting a failed program is the caller's job, not
|
|
134
|
+
* an exception path.
|
|
135
|
+
*/
|
|
136
|
+
export interface PtcRunResult {
|
|
137
|
+
/** Applied file policy and observed denial, when the provider enforces file policy. */
|
|
138
|
+
sandbox?: PtcRunSandbox;
|
|
139
|
+
/**
|
|
140
|
+
* The program's completion value (its top-level `return`), when it ran to
|
|
141
|
+
* completion and the value crossed the runtime's lossless-JSON boundary.
|
|
142
|
+
* Invalid or over-limit completions fail the run instead of substituting a
|
|
143
|
+
* rendered string; a failed or value-less run leaves this absent.
|
|
144
|
+
*/
|
|
145
|
+
value?: PtcJsonValue;
|
|
146
|
+
/**
|
|
147
|
+
* Captured text. Each source channel preserves emission order; interleaving
|
|
148
|
+
* across independent channels is backend-dependent. Bounded only as part of
|
|
149
|
+
* the outer result.
|
|
150
|
+
*/
|
|
151
|
+
logs: string[];
|
|
152
|
+
/** Present iff the run failed; see {@link PtcRunFailure} for the taxonomy. */
|
|
153
|
+
error?: PtcRunFailure;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qilin-agent/ptc-runtime",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"description": "Abstract PTC execution seam (ctx.ptcRuntime) for the QiLin",
|
|
4
|
+
"version": "3.1.4",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kkutysllb/QiLin.git",
|
|
11
|
+
"directory": "packages/ptc-runtime/ptc-runtime"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/types/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"default": "./lib/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./src/*": "./src/*",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"lib/index.js",
|
|
29
|
+
"lib/types/**/*.d.ts"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
34
|
+
"@qilin-agent/sandbox": "3.1.4"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@qilin-agent/kylin": "~4.0.3",
|
|
38
|
+
"@qilin-agent/sandbox": "3.1.4"
|
|
39
|
+
}
|
|
6
40
|
}
|