ummaya 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ummaya +76 -31
- package/bun.lock +10 -16
- package/npm-shrinkwrap.json +32 -10
- package/package.json +2 -1
- package/pyproject.toml +2 -2
- package/src/ummaya/engine/engine.py +17 -34
- package/src/ummaya/engine/models.py +10 -4
- package/src/ummaya/engine/query.py +108 -5
- package/src/ummaya/ipc/stdio.py +530 -30
- package/src/ummaya/tools/executor.py +52 -6
- package/src/ummaya/tools/hira/hospital_search.py +15 -2
- package/src/ummaya/tools/location_adapters.py +25 -1
- package/src/ummaya/tools/mvp_surface.py +47 -46
- package/src/ummaya/tools/nmc/emergency_search.py +53 -1
- package/src/ummaya/tools/search.py +63 -2
- package/tui/package.json +1 -1
- package/tui/src/query.ts +1 -1
- package/tui/src/services/api/claude.ts +53 -3
- package/tui/src/tools/AdapterTool/AdapterTool.ts +262 -4
- package/tui/src/tools/LookupPrimitive/prompt.ts +19 -30
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +12 -10
- package/tui/src/tools/SubmitPrimitive/prompt.ts +10 -6
- package/tui/src/tools/VerifyPrimitive/prompt.ts +10 -5
- package/uv.lock +1 -1
package/bin/ummaya
CHANGED
|
@@ -7,9 +7,27 @@ import { delimiter, dirname, join } from 'node:path'
|
|
|
7
7
|
import { fileURLToPath } from 'node:url'
|
|
8
8
|
|
|
9
9
|
const MINIMUM_BUN_VERSION = '1.3.0'
|
|
10
|
-
const
|
|
10
|
+
const PACKAGED_PRIMITIVE_TIMEOUT_MS = '90000'
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function currentLauncherPath() {
|
|
13
|
+
return realpathSync(fileURLToPath(import.meta.url))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function invokedLauncherPath() {
|
|
17
|
+
const argvPath = process.argv[1]
|
|
18
|
+
if (!argvPath) return null
|
|
19
|
+
try {
|
|
20
|
+
return realpathSync(argvPath)
|
|
21
|
+
} catch {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isDirectLaunch() {
|
|
27
|
+
return invokedLauncherPath() === currentLauncherPath()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function bunVersionAtLeast(version, minimum) {
|
|
13
31
|
const current = String(version)
|
|
14
32
|
.split('.')
|
|
15
33
|
.map((part) => Number.parseInt(part, 10))
|
|
@@ -62,7 +80,7 @@ function probeBunVersion(candidate) {
|
|
|
62
80
|
return (result.stdout || result.stderr).trim()
|
|
63
81
|
}
|
|
64
82
|
|
|
65
|
-
function launchWithCompatibleBun(currentVersion = null) {
|
|
83
|
+
function launchWithCompatibleBun(launcherPath, currentVersion = null) {
|
|
66
84
|
const checked = []
|
|
67
85
|
for (const candidate of collectBunCandidates()) {
|
|
68
86
|
const version = probeBunVersion(candidate)
|
|
@@ -94,17 +112,7 @@ function launchWithCompatibleBun(currentVersion = null) {
|
|
|
94
112
|
process.exit(1)
|
|
95
113
|
}
|
|
96
114
|
|
|
97
|
-
|
|
98
|
-
if (!runningBun) {
|
|
99
|
-
launchWithCompatibleBun()
|
|
100
|
-
}
|
|
101
|
-
if (!bunVersionAtLeast(runningBun.version, MINIMUM_BUN_VERSION)) {
|
|
102
|
-
launchWithCompatibleBun(runningBun.version)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const packageRoot = dirname(dirname(launcherPath))
|
|
106
|
-
|
|
107
|
-
function loadPackageDotenv(root) {
|
|
115
|
+
export function loadPackageDotenv(root, env = process.env) {
|
|
108
116
|
const envPath = join(root, '.env')
|
|
109
117
|
if (!existsSync(envPath)) return
|
|
110
118
|
const lines = readFileSync(envPath, 'utf8').split(/\r?\n/)
|
|
@@ -114,29 +122,66 @@ function loadPackageDotenv(root) {
|
|
|
114
122
|
const index = line.indexOf('=')
|
|
115
123
|
const key = line.slice(0, index).trim()
|
|
116
124
|
let value = line.slice(index + 1).trim()
|
|
117
|
-
if (!key ||
|
|
125
|
+
if (!key || env[key] !== undefined) continue
|
|
118
126
|
if (
|
|
119
127
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
120
128
|
(value.startsWith("'") && value.endsWith("'"))
|
|
121
129
|
) {
|
|
122
130
|
value = value.slice(1, -1)
|
|
123
131
|
}
|
|
124
|
-
|
|
132
|
+
env[key] = value
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function buildBackendCommand(root) {
|
|
137
|
+
const packagedPython = join(root, '.venv', 'bin', 'python')
|
|
138
|
+
if (existsSync(packagedPython)) {
|
|
139
|
+
return [packagedPython, '-m', 'ummaya.cli', '--ipc', 'stdio']
|
|
125
140
|
}
|
|
141
|
+
|
|
142
|
+
return ['uv', '--directory', root, 'run', '--frozen', '--no-dev', 'ummaya', '--ipc', 'stdio']
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function configurePackageEnv(root, env = process.env) {
|
|
146
|
+
env.UMMAYA_PACKAGE_ROOT = root
|
|
147
|
+
if (env.UMMAYA_ALLOW_BACKEND_CMD_OVERRIDE !== '1' || !env.UMMAYA_BACKEND_CMD_JSON) {
|
|
148
|
+
env.UMMAYA_BACKEND_CMD_JSON = JSON.stringify(buildBackendCommand(root))
|
|
149
|
+
}
|
|
150
|
+
env.UMMAYA_TUI_PRIMITIVE_TIMEOUT_MS ??= PACKAGED_PRIMITIVE_TIMEOUT_MS
|
|
151
|
+
return env
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function inspectLauncherAndExit() {
|
|
155
|
+
if (process.env.UMMAYA_LAUNCHER_INSPECT !== '1') return
|
|
156
|
+
process.stdout.write(
|
|
157
|
+
`${JSON.stringify({
|
|
158
|
+
packageRoot: process.env.UMMAYA_PACKAGE_ROOT,
|
|
159
|
+
backendCommand: JSON.parse(process.env.UMMAYA_BACKEND_CMD_JSON ?? '[]'),
|
|
160
|
+
primitiveTimeoutMs: process.env.UMMAYA_TUI_PRIMITIVE_TIMEOUT_MS,
|
|
161
|
+
})}\n`,
|
|
162
|
+
)
|
|
163
|
+
process.exit(0)
|
|
126
164
|
}
|
|
127
165
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
166
|
+
export async function main() {
|
|
167
|
+
const launcherPath = currentLauncherPath()
|
|
168
|
+
const runningBun = globalThis.Bun
|
|
169
|
+
if (!runningBun) {
|
|
170
|
+
launchWithCompatibleBun(launcherPath)
|
|
171
|
+
}
|
|
172
|
+
if (!bunVersionAtLeast(runningBun.version, MINIMUM_BUN_VERSION)) {
|
|
173
|
+
launchWithCompatibleBun(launcherPath, runningBun.version)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const packageRoot = dirname(dirname(launcherPath))
|
|
177
|
+
loadPackageDotenv(packageRoot)
|
|
178
|
+
configurePackageEnv(packageRoot)
|
|
179
|
+
inspectLauncherAndExit()
|
|
180
|
+
|
|
181
|
+
await import(join(packageRoot, 'tui/src/stubs/macro-preload.ts'))
|
|
182
|
+
await import(join(packageRoot, 'tui/src/entrypoints/cli.tsx'))
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (isDirectLaunch()) {
|
|
186
|
+
await main()
|
|
187
|
+
}
|
package/bun.lock
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"auto-bind": "^5.0.1",
|
|
40
40
|
"axios": "^1.15.2",
|
|
41
41
|
"bidi-js": "^1.0.3",
|
|
42
|
+
"bundle": "file:./tui/src/runtime/bundle-package",
|
|
42
43
|
"chalk": "^5.3.0",
|
|
43
44
|
"chokidar": "^4.0.0",
|
|
44
45
|
"cli-boxes": "^4.0.1",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"proper-lockfile": "^4.1.2",
|
|
65
66
|
"qrcode": "^1.5.4",
|
|
66
67
|
"react": "^19.2.0",
|
|
68
|
+
"react-reconciler": "0.33.0",
|
|
67
69
|
"semver": "^7.7.4",
|
|
68
70
|
"shell-quote": "^1.8.3",
|
|
69
71
|
"supports-hyperlinks": "^4.4.0",
|
|
@@ -446,6 +448,8 @@
|
|
|
446
448
|
|
|
447
449
|
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
|
448
450
|
|
|
451
|
+
"bundle": ["bundle@file:tui/src/runtime/bundle-package", {}],
|
|
452
|
+
|
|
449
453
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
|
450
454
|
|
|
451
455
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
|
@@ -892,7 +896,7 @@
|
|
|
892
896
|
|
|
893
897
|
"react": ["react@19.2.6", "", {}, "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q=="],
|
|
894
898
|
|
|
895
|
-
"react-reconciler": ["react-reconciler@0.
|
|
899
|
+
"react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
|
|
896
900
|
|
|
897
901
|
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
|
898
902
|
|
|
@@ -916,7 +920,7 @@
|
|
|
916
920
|
|
|
917
921
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
918
922
|
|
|
919
|
-
"scheduler": ["scheduler@0.
|
|
923
|
+
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
|
920
924
|
|
|
921
925
|
"semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
|
922
926
|
|
|
@@ -1132,6 +1136,8 @@
|
|
|
1132
1136
|
|
|
1133
1137
|
"ink/cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
|
1134
1138
|
|
|
1139
|
+
"ink/react-reconciler": ["react-reconciler@0.32.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ=="],
|
|
1140
|
+
|
|
1135
1141
|
"ink/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
1136
1142
|
|
|
1137
1143
|
"make-dir/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
@@ -1156,8 +1162,6 @@
|
|
|
1156
1162
|
|
|
1157
1163
|
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
1158
1164
|
|
|
1159
|
-
"wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
|
1160
|
-
|
|
1161
1165
|
"xss/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
|
1162
1166
|
|
|
1163
1167
|
"yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
@@ -1188,8 +1192,6 @@
|
|
|
1188
1192
|
|
|
1189
1193
|
"cli-truncate/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
|
|
1190
1194
|
|
|
1191
|
-
"cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
|
1192
|
-
|
|
1193
1195
|
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
1194
1196
|
|
|
1195
1197
|
"cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
@@ -1208,6 +1210,8 @@
|
|
|
1208
1210
|
|
|
1209
1211
|
"gaxios/https-proxy-agent/agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
|
1210
1212
|
|
|
1213
|
+
"ink/react-reconciler/scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
|
1214
|
+
|
|
1211
1215
|
"pdfjs-dist/canvas/simple-get": ["simple-get@3.1.1", "", { "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA=="],
|
|
1212
1216
|
|
|
1213
1217
|
"qrcode/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
|
|
@@ -1224,8 +1228,6 @@
|
|
|
1224
1228
|
|
|
1225
1229
|
"wide-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
1226
1230
|
|
|
1227
|
-
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
|
1228
|
-
|
|
1229
1231
|
"yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
1230
1232
|
|
|
1231
1233
|
"yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
@@ -1240,8 +1242,6 @@
|
|
|
1240
1242
|
|
|
1241
1243
|
"@inquirer/core/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
1242
1244
|
|
|
1243
|
-
"cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
|
1244
|
-
|
|
1245
1245
|
"pdfjs-dist/canvas/simple-get/decompress-response": ["decompress-response@4.2.1", "", { "dependencies": { "mimic-response": "^2.0.0" } }, "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw=="],
|
|
1246
1246
|
|
|
1247
1247
|
"qrcode/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
@@ -1264,12 +1264,6 @@
|
|
|
1264
1264
|
|
|
1265
1265
|
"qrcode/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
1266
1266
|
|
|
1267
|
-
"qrcode/yargs/cliui/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
|
1268
|
-
|
|
1269
1267
|
"qrcode/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
|
1270
|
-
|
|
1271
|
-
"qrcode/yargs/cliui/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
1272
|
-
|
|
1273
|
-
"qrcode/yargs/cliui/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
1274
1268
|
}
|
|
1275
1269
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ummaya",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "ummaya",
|
|
9
|
-
"version": "0.2.
|
|
9
|
+
"version": "0.2.2",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@alcalzone/ansi-tokenize": "^0.3.0",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"proper-lockfile": "^4.1.2",
|
|
70
70
|
"qrcode": "^1.5.4",
|
|
71
71
|
"react": "^19.2.0",
|
|
72
|
+
"react-reconciler": "0.33.0",
|
|
72
73
|
"semver": "^7.7.4",
|
|
73
74
|
"shell-quote": "^1.8.3",
|
|
74
75
|
"supports-hyperlinks": "^4.4.0",
|
|
@@ -4990,6 +4991,27 @@
|
|
|
4990
4991
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
4991
4992
|
}
|
|
4992
4993
|
},
|
|
4994
|
+
"node_modules/ink/node_modules/react-reconciler": {
|
|
4995
|
+
"version": "0.32.0",
|
|
4996
|
+
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz",
|
|
4997
|
+
"integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==",
|
|
4998
|
+
"license": "MIT",
|
|
4999
|
+
"dependencies": {
|
|
5000
|
+
"scheduler": "^0.26.0"
|
|
5001
|
+
},
|
|
5002
|
+
"engines": {
|
|
5003
|
+
"node": ">=0.10.0"
|
|
5004
|
+
},
|
|
5005
|
+
"peerDependencies": {
|
|
5006
|
+
"react": "^19.1.0"
|
|
5007
|
+
}
|
|
5008
|
+
},
|
|
5009
|
+
"node_modules/ink/node_modules/scheduler": {
|
|
5010
|
+
"version": "0.26.0",
|
|
5011
|
+
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
|
|
5012
|
+
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
|
|
5013
|
+
"license": "MIT"
|
|
5014
|
+
},
|
|
4993
5015
|
"node_modules/ink/node_modules/signal-exit": {
|
|
4994
5016
|
"version": "3.0.7",
|
|
4995
5017
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
|
@@ -6294,18 +6316,18 @@
|
|
|
6294
6316
|
}
|
|
6295
6317
|
},
|
|
6296
6318
|
"node_modules/react-reconciler": {
|
|
6297
|
-
"version": "0.
|
|
6298
|
-
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.
|
|
6299
|
-
"integrity": "sha512-
|
|
6319
|
+
"version": "0.33.0",
|
|
6320
|
+
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz",
|
|
6321
|
+
"integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==",
|
|
6300
6322
|
"license": "MIT",
|
|
6301
6323
|
"dependencies": {
|
|
6302
|
-
"scheduler": "^0.
|
|
6324
|
+
"scheduler": "^0.27.0"
|
|
6303
6325
|
},
|
|
6304
6326
|
"engines": {
|
|
6305
6327
|
"node": ">=0.10.0"
|
|
6306
6328
|
},
|
|
6307
6329
|
"peerDependencies": {
|
|
6308
|
-
"react": "^19.
|
|
6330
|
+
"react": "^19.2.0"
|
|
6309
6331
|
}
|
|
6310
6332
|
},
|
|
6311
6333
|
"node_modules/readable-stream": {
|
|
@@ -6450,9 +6472,9 @@
|
|
|
6450
6472
|
"license": "MIT"
|
|
6451
6473
|
},
|
|
6452
6474
|
"node_modules/scheduler": {
|
|
6453
|
-
"version": "0.
|
|
6454
|
-
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.
|
|
6455
|
-
"integrity": "sha512-
|
|
6475
|
+
"version": "0.27.0",
|
|
6476
|
+
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
|
6477
|
+
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
|
6456
6478
|
"license": "MIT"
|
|
6457
6479
|
},
|
|
6458
6480
|
"node_modules/semver": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ummaya",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Conversational multi-agent harness for Korean public-service channels",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"proper-lockfile": "^4.1.2",
|
|
130
130
|
"qrcode": "^1.5.4",
|
|
131
131
|
"react": "^19.2.0",
|
|
132
|
+
"react-reconciler": "0.33.0",
|
|
132
133
|
"semver": "^7.7.4",
|
|
133
134
|
"shell-quote": "^1.8.3",
|
|
134
135
|
"supports-hyperlinks": "^4.4.0",
|
package/pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ummaya"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Conversational multi-agent platform for Korean public APIs"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -314,7 +314,7 @@ min_confidence = 80
|
|
|
314
314
|
|
|
315
315
|
[tool.commitizen]
|
|
316
316
|
name = "cz_conventional_commits"
|
|
317
|
-
version = "0.2.
|
|
317
|
+
version = "0.2.2"
|
|
318
318
|
tag_format = "v$version"
|
|
319
319
|
|
|
320
320
|
# PyTorch CPU-only wheel for Docker image size discipline (SC-1: ≤ 2 GB).
|
|
@@ -75,17 +75,6 @@ def _contains_location_dependent_key(value: object) -> bool:
|
|
|
75
75
|
return False
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
def _allowed_core_tools_for_available_adapters(
|
|
79
|
-
visible_primitives: set[str],
|
|
80
|
-
has_location_dependent_schema: bool,
|
|
81
|
-
) -> frozenset[str] | None:
|
|
82
|
-
"""Constrain root primitive exposure for location-independent find turns."""
|
|
83
|
-
|
|
84
|
-
if visible_primitives == {"find"} and not has_location_dependent_schema:
|
|
85
|
-
return frozenset({"find"})
|
|
86
|
-
return None
|
|
87
|
-
|
|
88
|
-
|
|
89
78
|
class QueryEngine:
|
|
90
79
|
"""Per-session orchestrator for the UMMAYA query engine.
|
|
91
80
|
|
|
@@ -216,7 +205,7 @@ class QueryEngine:
|
|
|
216
205
|
ChatMessage(role="user", content=assembled.turn_attachment.content),
|
|
217
206
|
)
|
|
218
207
|
|
|
219
|
-
dynamic_adapter_message,
|
|
208
|
+
dynamic_adapter_message, turn_tool_ids = self._build_available_adapters_context(
|
|
220
209
|
user_message
|
|
221
210
|
)
|
|
222
211
|
if dynamic_adapter_message is not None:
|
|
@@ -235,7 +224,7 @@ class QueryEngine:
|
|
|
235
224
|
tool_registry=self._tool_registry,
|
|
236
225
|
config=self._config,
|
|
237
226
|
session_context=self._permission_session,
|
|
238
|
-
|
|
227
|
+
turn_tool_ids=turn_tool_ids,
|
|
239
228
|
turn_start_message_index=turn_start_message_index,
|
|
240
229
|
)
|
|
241
230
|
|
|
@@ -281,13 +270,13 @@ class QueryEngine:
|
|
|
281
270
|
def _build_available_adapters_message(self, user_message: str) -> ChatMessage | None:
|
|
282
271
|
"""Inject BM25 adapter candidates for the current citizen utterance."""
|
|
283
272
|
|
|
284
|
-
message,
|
|
273
|
+
message, _turn_tool_ids = self._build_available_adapters_context(user_message)
|
|
285
274
|
return message
|
|
286
275
|
|
|
287
276
|
def _build_available_adapters_context(
|
|
288
277
|
self, user_message: str
|
|
289
|
-
) -> tuple[ChatMessage | None,
|
|
290
|
-
"""Build dynamic adapter context and per-turn
|
|
278
|
+
) -> tuple[ChatMessage | None, tuple[str, ...]]:
|
|
279
|
+
"""Build dynamic adapter context and per-turn concrete tool exposure."""
|
|
291
280
|
|
|
292
281
|
try:
|
|
293
282
|
from ummaya.tools.search import search # noqa: PLC0415
|
|
@@ -300,11 +289,10 @@ class QueryEngine:
|
|
|
300
289
|
)
|
|
301
290
|
except Exception: # noqa: BLE001
|
|
302
291
|
logger.exception("available_adapters auto-inject failed")
|
|
303
|
-
return None,
|
|
292
|
+
return None, ()
|
|
304
293
|
|
|
305
294
|
adapter_lines: list[str] = []
|
|
306
|
-
|
|
307
|
-
has_location_dependent_schema = False
|
|
295
|
+
selected_tool_ids: list[str] = []
|
|
308
296
|
primary_find_without_location = False
|
|
309
297
|
visible_count = 0
|
|
310
298
|
for candidate in candidates:
|
|
@@ -312,6 +300,8 @@ class QueryEngine:
|
|
|
312
300
|
tool = self._tool_registry.find(candidate.tool_id)
|
|
313
301
|
except ToolNotFoundError:
|
|
314
302
|
continue
|
|
303
|
+
if candidate.score <= 0:
|
|
304
|
+
continue
|
|
315
305
|
if tool.is_core or tool.ministry == "UMMAYA":
|
|
316
306
|
continue
|
|
317
307
|
primitive = candidate.primitive if isinstance(candidate.primitive, str) else None
|
|
@@ -324,15 +314,12 @@ class QueryEngine:
|
|
|
324
314
|
)
|
|
325
315
|
if visible_count > 0 and primary_find_without_location and requires_location:
|
|
326
316
|
continue
|
|
327
|
-
if primitive is not None:
|
|
328
|
-
visible_primitives.add(primitive)
|
|
329
|
-
if requires_location:
|
|
330
|
-
has_location_dependent_schema = True
|
|
331
317
|
schema_json = json.dumps(
|
|
332
318
|
candidate.input_schema_json,
|
|
333
319
|
ensure_ascii=False,
|
|
334
320
|
sort_keys=True,
|
|
335
321
|
)
|
|
322
|
+
selected_tool_ids.append(candidate.tool_id)
|
|
336
323
|
adapter_lines.extend(
|
|
337
324
|
[
|
|
338
325
|
f"- tool_id: {candidate.tool_id}",
|
|
@@ -340,8 +327,7 @@ class QueryEngine:
|
|
|
340
327
|
f" description: {candidate.llm_description or tool.name_ko}",
|
|
341
328
|
f" required_params: {candidate.required_params}",
|
|
342
329
|
f" input_schema_json: {schema_json}",
|
|
343
|
-
f" call_hint: {candidate.
|
|
344
|
-
f'{{"tool_id":"{candidate.tool_id}","params":{{...}}}})',
|
|
330
|
+
f" call_hint: {candidate.tool_id}({{...}})",
|
|
345
331
|
f" policy_url: {candidate.real_classification_url or ''}",
|
|
346
332
|
]
|
|
347
333
|
)
|
|
@@ -350,19 +336,16 @@ class QueryEngine:
|
|
|
350
336
|
break
|
|
351
337
|
|
|
352
338
|
if not adapter_lines:
|
|
353
|
-
return None,
|
|
354
|
-
|
|
355
|
-
allowed_core_tool_ids = _allowed_core_tools_for_available_adapters(
|
|
356
|
-
visible_primitives,
|
|
357
|
-
has_location_dependent_schema,
|
|
358
|
-
)
|
|
339
|
+
return None, ()
|
|
359
340
|
|
|
360
341
|
content = "\n".join(
|
|
361
342
|
[
|
|
362
343
|
"<available_adapters>",
|
|
363
344
|
"Use these adapter candidates for this citizen request. "
|
|
364
|
-
"
|
|
365
|
-
"
|
|
345
|
+
"Call the function named exactly as tool_id with that adapter's "
|
|
346
|
+
"schema arguments. Do not wrap adapter calls in root primitives "
|
|
347
|
+
"such as find({tool_id, params}), locate({tool_id, params}), "
|
|
348
|
+
"check({tool_id, params}), or send({tool_id, params}). "
|
|
366
349
|
"Do not call locate just because the citizen text contains a "
|
|
367
350
|
"city/province name; treat that as the dataset/filter term. "
|
|
368
351
|
"Call locate only when the selected adapter schema requires "
|
|
@@ -371,7 +354,7 @@ class QueryEngine:
|
|
|
371
354
|
"</available_adapters>",
|
|
372
355
|
]
|
|
373
356
|
)
|
|
374
|
-
return ChatMessage(role="system", content=content),
|
|
357
|
+
return ChatMessage(role="system", content=content), tuple(selected_tool_ids)
|
|
375
358
|
|
|
376
359
|
def set_permission_session(self, session: SessionContext | None) -> None:
|
|
377
360
|
"""Update the permission-pipeline session used for subsequent turns.
|
|
@@ -121,11 +121,17 @@ class QueryContext(BaseModel):
|
|
|
121
121
|
"""
|
|
122
122
|
|
|
123
123
|
allowed_core_tool_ids: frozenset[str] | None = None
|
|
124
|
-
"""
|
|
124
|
+
"""Legacy per-turn allow-list for primitive wrappers.
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
Preserved for callers that still expose the old root primitives. New turns
|
|
127
|
+
should prefer ``turn_tool_ids`` so the model sees concrete adapter schemas.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
turn_tool_ids: tuple[str, ...] = ()
|
|
131
|
+
"""Concrete adapter tool IDs selected for this citizen turn.
|
|
132
|
+
|
|
133
|
+
When populated, the query loop exports these concrete adapter schemas as the
|
|
134
|
+
provider tool surface instead of dumping the root primitive wrappers.
|
|
129
135
|
"""
|
|
130
136
|
|
|
131
137
|
turn_start_message_index: int = 0
|