rtrt-agent 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +12 -10
- package/README.md +13 -11
- package/package.json +1 -1
- package/rtrt-provenance.js +9 -85
package/README.ko.md
CHANGED
|
@@ -7,14 +7,14 @@ hook 사이에서 상위 session, agent, worktree, invocation 및 permission bro
|
|
|
7
7
|
## 설치
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
npm install rtrt-agent@0.1.
|
|
10
|
+
npm install rtrt-agent@0.1.1
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
`opencode.json`의 단수형 `plugin` 배열에 패키지를 등록합니다.
|
|
14
14
|
|
|
15
15
|
```json
|
|
16
16
|
{
|
|
17
|
-
"plugin": ["rtrt-agent"]
|
|
17
|
+
"plugin": ["rtrt-agent@0.1.1"]
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -22,18 +22,20 @@ OpenCode는 이름 있는 `RtrtProvenance` export를 로드합니다. 이 패키
|
|
|
22
22
|
default export를 제공하지 않습니다. 선택 사항인 RTRT TUI statusline은 별도 소스
|
|
23
23
|
통합으로 유지되며 이 패키지에서 export하거나 pack하지 않습니다.
|
|
24
24
|
|
|
25
|
-
`rtrt setup --agent opencode --apply`는
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
`rtrt setup --agent opencode --apply`는 전체 RTRT 통합을 관리하지만 npm 설치는 수행하지
|
|
26
|
+
않으며, 설정된 패키지는 OpenCode가 시작할 때 설치합니다. Setup은 먼저 정확한
|
|
27
|
+
`rtrt-agent@0.1.1` 등록과 모든 대체 관리 asset을 기록합니다. 이 기록이 성공한 뒤에만
|
|
28
|
+
인식된 legacy RTRT plugin을 제거하며, 이전 단계가 실패하면 legacy runtime을 보존합니다.
|
|
29
|
+
Setup은 `rtrt-agent`의 정확히 일치하는 bare, pinned, ranged, tuple, object 형식만 소유하고
|
|
30
|
+
정확한 `"rtrt-agent@0.1.1"` string 하나로 정규화합니다. 이전의 미게시 `rtrt`와 초안
|
|
31
|
+
`rtrt-opencode` 패키지 spec은 외부 값이며 순서를 유지합니다. 위 직접 등록과
|
|
32
|
+
`opencode plugin rtrt-agent@0.1.1 --global`은 계속 유효합니다.
|
|
31
33
|
|
|
32
34
|
관리 agent 소유권 상태는 다음 순서의 첫 비어 있지 않은 root에서 읽습니다.
|
|
33
35
|
`$OPENCODE_CONFIG_DIR`, `$XDG_CONFIG_HOME/opencode`, `~/.config/opencode`. 공존은 OMO
|
|
34
36
|
4.19.4를 대상으로 CI에서 검사하고 OpenCode 1.18.29에서 직접 검증했으며, 어느 쪽도
|
|
35
|
-
미래 버전 지원을 보장하지 않습니다. RTRT
|
|
36
|
-
`rtrt-agent@0.1.
|
|
37
|
+
미래 버전 지원을 보장하지 않습니다. 통합 RTRT 릴리스 워크플로는 정확한
|
|
38
|
+
`rtrt-agent@0.1.1` 패키지를 일치하는 Rust 릴리스와 함께 게시합니다.
|
|
37
39
|
|
|
38
40
|
## 라이선스
|
|
39
41
|
|
package/README.md
CHANGED
|
@@ -7,14 +7,14 @@ hooks while keeping the broker loopback-only.
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
npm install rtrt-agent@0.1.
|
|
10
|
+
npm install rtrt-agent@0.1.1
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Register the package in the singular `plugin` array in `opencode.json`:
|
|
14
14
|
|
|
15
15
|
```json
|
|
16
16
|
{
|
|
17
|
-
"plugin": ["rtrt-agent"]
|
|
17
|
+
"plugin": ["rtrt-agent@0.1.1"]
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -22,19 +22,21 @@ OpenCode loads the named `RtrtProvenance` export. The package intentionally has
|
|
|
22
22
|
default export. The optional RTRT TUI statusline remains a separate source integration
|
|
23
23
|
and is not exported or packed by this package.
|
|
24
24
|
|
|
25
|
-
`rtrt setup --agent opencode --apply`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
`
|
|
25
|
+
`rtrt setup --agent opencode --apply` manages the full RTRT integration but performs no
|
|
26
|
+
npm installation; OpenCode installs the configured package at startup. Setup first writes
|
|
27
|
+
the exact `rtrt-agent@0.1.1` registration and every replacement managed asset. Only after
|
|
28
|
+
those writes succeed does it remove a recognized legacy RTRT plugin; an earlier failure
|
|
29
|
+
preserves the legacy runtime. Setup owns exact bare, pinned, ranged, tuple, and object forms
|
|
30
|
+
of `rtrt-agent` only and normalizes them to one exact `"rtrt-agent@0.1.1"` string. Old
|
|
31
|
+
unpublished `rtrt` and draft `rtrt-opencode` package specs are foreign and retain their
|
|
32
|
+
order. The direct registration above and `opencode plugin rtrt-agent@0.1.1 --global`
|
|
33
|
+
remain valid.
|
|
32
34
|
|
|
33
35
|
Managed-agent ownership state is read from the first nonempty root in this order:
|
|
34
36
|
`$OPENCODE_CONFIG_DIR`, `$XDG_CONFIG_HOME/opencode`, then `~/.config/opencode`.
|
|
35
37
|
Coexistence is CI-gated against OMO 4.19.4 and was verified on OpenCode 1.18.29; neither
|
|
36
|
-
is a future-version guarantee.
|
|
37
|
-
|
|
38
|
+
is a future-version guarantee. The unified RTRT release workflow publishes the exact
|
|
39
|
+
`rtrt-agent@0.1.1` package together with the matching Rust release.
|
|
38
40
|
|
|
39
41
|
## License
|
|
40
42
|
|
package/package.json
CHANGED
package/rtrt-provenance.js
CHANGED
|
@@ -128,94 +128,19 @@ const loadManagedAgents = async (statePath) => {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
let probe = target
|
|
138
|
-
while (true) {
|
|
139
|
-
try {
|
|
140
|
-
const resolved = await realpath(probe)
|
|
141
|
-
return context.bounds.some((bound) => isWithin(bound, resolved))
|
|
142
|
-
} catch (error) {
|
|
143
|
-
if (error?.code !== "ENOENT" && error?.code !== "ENOTDIR") return false
|
|
144
|
-
const parent = path.dirname(probe)
|
|
145
|
-
if (parent === probe || !context.bounds.some((bound) => isWithin(bound, parent))) return false
|
|
146
|
-
probe = parent
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const splitOptions = (args, valueOptions = new Set()) => {
|
|
152
|
-
const operands = []
|
|
153
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
154
|
-
const argument = args[index]
|
|
155
|
-
if (argument === "--") {
|
|
156
|
-
operands.push(...args.slice(index + 1))
|
|
157
|
-
break
|
|
158
|
-
}
|
|
159
|
-
if (!argument.startsWith("-") || argument === "-") {
|
|
160
|
-
operands.push(argument)
|
|
161
|
-
continue
|
|
162
|
-
}
|
|
163
|
-
const [option, attached] = argument.split(/=(.*)/s, 2)
|
|
164
|
-
if (valueOptions.has(option)) {
|
|
165
|
-
const value = attached ?? args[++index]
|
|
166
|
-
if (!value) return
|
|
167
|
-
operands.push(value)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return operands
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const allPathsInside = async (root, operands) => {
|
|
174
|
-
if (!operands) return false
|
|
175
|
-
for (const operand of operands) if (!(await realisticInside(root, operand))) return false
|
|
176
|
-
return true
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const READ_COMMANDS = new Set(["cat", "wc", "stat"])
|
|
180
|
-
|
|
131
|
+
// Auto-approval deliberately covers no command that names a path. This hook
|
|
132
|
+
// resolves operands when the permission is evaluated, but the shell resolves
|
|
133
|
+
// them again when it runs, so anyone who can write to the checkout can swap an
|
|
134
|
+
// approved file for a symlink in between and read an arbitrary file into the
|
|
135
|
+
// model's context. `pwd` is the only command whose meaning cannot be redirected
|
|
136
|
+
// that way; everything else stays at "ask".
|
|
181
137
|
const safeCommand = async (command, root) => {
|
|
138
|
+
if (typeof command !== "string" || /[{}]/.test(command)) return false
|
|
182
139
|
const tokens = tokenizeCommand(command)
|
|
183
140
|
if (!tokens || !root || !BARE_COMMAND.test(tokens[0]) || tokens.some((item) => URL_ARGUMENT.test(item))) return false
|
|
184
141
|
const [executable, ...args] = tokens
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if ((path.isAbsolute(value) || value.includes("/") || value.includes("\\") || value.startsWith(".")) && !(await realisticInside(root, value))) return false
|
|
188
|
-
}
|
|
189
|
-
if (executable === "pwd") return args.every((item) => item === "-L" || item === "-P")
|
|
190
|
-
if (executable === "ls") {
|
|
191
|
-
if (args.some((item) => item.startsWith("-") && !/^-[AacdFfghikLlmnopqRrSstuUx1]+$/.test(item))) return false
|
|
192
|
-
return allPathsInside(root, args.filter((item) => !item.startsWith("-")))
|
|
193
|
-
}
|
|
194
|
-
if (READ_COMMANDS.has(executable)) {
|
|
195
|
-
if (args.some((item) => item.startsWith("-") && item !== "--")) return false
|
|
196
|
-
const operands = splitOptions(args)
|
|
197
|
-
return Boolean(operands?.length) && allPathsInside(root, operands)
|
|
198
|
-
}
|
|
199
|
-
if (["head", "tail"].includes(executable)) {
|
|
200
|
-
const operands = []
|
|
201
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
202
|
-
const argument = args[index]
|
|
203
|
-
if (argument === "-q" || argument === "--quiet" || argument === "--silent" || argument === "-v" || argument === "--verbose") continue
|
|
204
|
-
const attached = argument.match(/^(?:-n|--lines|-c|--bytes)=(.*)$/)
|
|
205
|
-
if (attached) {
|
|
206
|
-
if (!/^[-+]?\d+$/.test(attached[1])) return false
|
|
207
|
-
continue
|
|
208
|
-
}
|
|
209
|
-
if (["-n", "--lines", "-c", "--bytes"].includes(argument)) {
|
|
210
|
-
if (!/^[-+]?\d+$/.test(args[++index] ?? "")) return false
|
|
211
|
-
continue
|
|
212
|
-
}
|
|
213
|
-
if (argument.startsWith("-")) return false
|
|
214
|
-
operands.push(argument)
|
|
215
|
-
}
|
|
216
|
-
return operands.length > 0 && allPathsInside(root, operands)
|
|
217
|
-
}
|
|
218
|
-
return false
|
|
142
|
+
if (executable !== "pwd") return false
|
|
143
|
+
return args.every((item) => item === "-L" || item === "-P")
|
|
219
144
|
}
|
|
220
145
|
|
|
221
146
|
const defaultClientFactory = async (options) => {
|
|
@@ -226,7 +151,6 @@ const defaultClientFactory = async (options) => {
|
|
|
226
151
|
const RTRT_AGENT_TOOLS = new Set([
|
|
227
152
|
"rtrt_agent_call",
|
|
228
153
|
"rtrt_agent_route",
|
|
229
|
-
"rtrt_team_dispatch",
|
|
230
154
|
])
|
|
231
155
|
|
|
232
156
|
const sanitizeSessionID = (sessionID) => {
|