@piagent/platform 1.2.0 → 1.2.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/CHANGELOG.md +133 -1
- package/README.md +1 -1
- package/docs/command-reference-vietnamese.md +8 -3
- package/docs/distribution-standard.md +7 -7
- package/docs/mcp-and-tools.md +49 -3
- package/docs/operator-manual-vietnamese.md +20 -8
- package/docs/publishing-for-teams.md +1 -0
- package/docs/release-install-policy.md +6 -6
- package/docs/security-threat-model.md +4 -3
- package/docs/team-onboarding.md +3 -3
- package/docs/usage-observability.md +29 -0
- package/docs-site/architecture.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/mcp-approval.html +54 -2
- package/docs-site/content/quickstart.html +1 -1
- package/docs-site/index.html +1 -1
- package/docs-site/mcp-approval.html +55 -3
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +2 -2
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/package.json +1 -1
- package/packages/piagent-core/capabilities/capability-core.js +41 -4
- package/packages/piagent-core/capabilities/capability-sources.js +73 -12
- package/packages/piagent-core/extensions/piagent-guard.ts +139 -25
- package/packages/piagent-core/extensions/policy-core.js +1586 -98
- package/packages/piagent-core/mcp/mcp-approval-store.js +56 -15
- package/packages/piagent-core/mcp/mcp-auth-readiness.js +31 -3
- package/packages/piagent-core/mcp/mcp-command-actions.js +139 -30
- package/packages/piagent-core/mcp/mcp-config-layers.js +339 -6
- package/packages/piagent-core/mcp/mcp-import-kinds.js +240 -0
- package/packages/piagent-core/mcp/mcp-server-entry.js +51 -0
- package/packages/piagent-core/mcp/mcp-session-view.js +55 -4
- package/packages/piagent-core/mcp/mcp-tool-naming.js +90 -0
- package/packages/piagent-core/package.json +1 -1
- package/scripts/configure-model-scope.sh +19 -3
- package/scripts/configure-subagents.sh +17 -4
- package/scripts/init-project.sh +15 -8
- package/scripts/mcp-manage.mjs +111 -22
- package/scripts/pi-model-catalog.sh +11 -1
- package/scripts/pi-session-stats.sh +27 -1
- package/scripts/pi-usage-history.mjs +567 -0
- package/scripts/quality-benchmark.sh +37 -9
- package/scripts/setup.sh +21 -13
- package/scripts/uninstall-global.sh +10 -4
- package/scripts/verify-local.sh +19 -0
- package/scripts/verify-release-identity.mjs +29 -0
|
@@ -31,6 +31,14 @@ if [[ -z "$PROJECT_PATH" ]]; then
|
|
|
31
31
|
usage
|
|
32
32
|
exit 2
|
|
33
33
|
fi
|
|
34
|
+
# The project path is positional and comes first, so omitting it hands the first
|
|
35
|
+
# flag to `cd` and the run dies somewhere further down complaining about an
|
|
36
|
+
# option. Say what is actually wrong instead.
|
|
37
|
+
if [[ "$PROJECT_PATH" == -* ]]; then
|
|
38
|
+
echo "FAIL: the project path comes first, before any flag; received: $PROJECT_PATH" >&2
|
|
39
|
+
usage >&2
|
|
40
|
+
exit 2
|
|
41
|
+
fi
|
|
34
42
|
shift || true
|
|
35
43
|
|
|
36
44
|
PROJECT_PATH="$(cd "$PROJECT_PATH" && pwd)"
|
|
@@ -45,6 +53,17 @@ COST=""
|
|
|
45
53
|
DURATION=""
|
|
46
54
|
NOTES=""
|
|
47
55
|
|
|
56
|
+
# A flag left without a value otherwise consumes the next flag as its value, and
|
|
57
|
+
# the run continues on a record that says something nobody typed.
|
|
58
|
+
require_value() {
|
|
59
|
+
local option="$1"
|
|
60
|
+
local value="${2:-}"
|
|
61
|
+
if [[ -z "$value" || "$value" == --* ]]; then
|
|
62
|
+
echo "Missing value for $option" >&2
|
|
63
|
+
exit 2
|
|
64
|
+
fi
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
while [[ $# -gt 0 ]]; do
|
|
49
68
|
case "$1" in
|
|
50
69
|
--init)
|
|
@@ -56,39 +75,48 @@ while [[ $# -gt 0 ]]; do
|
|
|
56
75
|
shift
|
|
57
76
|
;;
|
|
58
77
|
--scenario)
|
|
59
|
-
|
|
78
|
+
require_value "$1" "${2:-}"
|
|
79
|
+
SCENARIO="$2"
|
|
60
80
|
shift 2
|
|
61
81
|
;;
|
|
62
82
|
--surface|--agent)
|
|
63
|
-
|
|
83
|
+
require_value "$1" "${2:-}"
|
|
84
|
+
SURFACE="$2"
|
|
64
85
|
shift 2
|
|
65
86
|
;;
|
|
66
87
|
--result)
|
|
67
|
-
|
|
88
|
+
require_value "$1" "${2:-}"
|
|
89
|
+
RESULT="$2"
|
|
68
90
|
shift 2
|
|
69
91
|
;;
|
|
70
92
|
--task-file)
|
|
71
|
-
|
|
93
|
+
require_value "$1" "${2:-}"
|
|
94
|
+
TASK_FILE="$2"
|
|
72
95
|
shift 2
|
|
73
96
|
;;
|
|
74
97
|
--verify)
|
|
75
|
-
|
|
98
|
+
require_value "$1" "${2:-}"
|
|
99
|
+
VERIFY_CMD="$2"
|
|
76
100
|
shift 2
|
|
77
101
|
;;
|
|
78
102
|
--tokens)
|
|
79
|
-
|
|
103
|
+
require_value "$1" "${2:-}"
|
|
104
|
+
TOKENS="$2"
|
|
80
105
|
shift 2
|
|
81
106
|
;;
|
|
82
107
|
--cost)
|
|
83
|
-
|
|
108
|
+
require_value "$1" "${2:-}"
|
|
109
|
+
COST="$2"
|
|
84
110
|
shift 2
|
|
85
111
|
;;
|
|
86
112
|
--duration)
|
|
87
|
-
|
|
113
|
+
require_value "$1" "${2:-}"
|
|
114
|
+
DURATION="$2"
|
|
88
115
|
shift 2
|
|
89
116
|
;;
|
|
90
117
|
--notes)
|
|
91
|
-
|
|
118
|
+
require_value "$1" "${2:-}"
|
|
119
|
+
NOTES="$2"
|
|
92
120
|
shift 2
|
|
93
121
|
;;
|
|
94
122
|
-h|--help)
|
package/scripts/setup.sh
CHANGED
|
@@ -85,21 +85,24 @@ SKIP_AGENTS=false
|
|
|
85
85
|
SKIP_REVIEW=false
|
|
86
86
|
DRY_RUN=false
|
|
87
87
|
|
|
88
|
+
require_value() {
|
|
89
|
+
local option="$1"
|
|
90
|
+
local value="${2:-}"
|
|
91
|
+
if [[ -z "$value" || "$value" == --* ]]; then
|
|
92
|
+
echo "Missing value for $option" >&2
|
|
93
|
+
exit 2
|
|
94
|
+
fi
|
|
95
|
+
}
|
|
96
|
+
|
|
88
97
|
while [[ $# -gt 0 ]]; do
|
|
89
98
|
case "$1" in
|
|
90
99
|
--profile)
|
|
91
|
-
|
|
92
|
-
echo "Missing value for --profile" >&2
|
|
93
|
-
exit 2
|
|
94
|
-
fi
|
|
100
|
+
require_value "$1" "${2:-}"
|
|
95
101
|
PROFILE_INPUT="$2"
|
|
96
102
|
shift 2
|
|
97
103
|
;;
|
|
98
104
|
--package-source)
|
|
99
|
-
|
|
100
|
-
echo "Missing value for --package-source" >&2
|
|
101
|
-
exit 2
|
|
102
|
-
fi
|
|
105
|
+
require_value "$1" "${2:-}"
|
|
103
106
|
PACKAGE_SOURCE="$2"
|
|
104
107
|
shift 2
|
|
105
108
|
;;
|
|
@@ -124,7 +127,8 @@ while [[ $# -gt 0 ]]; do
|
|
|
124
127
|
shift
|
|
125
128
|
;;
|
|
126
129
|
--mcp-preset)
|
|
127
|
-
|
|
130
|
+
require_value "$1" "${2:-}"
|
|
131
|
+
MCP_PRESET="$2"
|
|
128
132
|
MCP_PRESET_EXPLICIT=true
|
|
129
133
|
shift 2
|
|
130
134
|
;;
|
|
@@ -137,11 +141,13 @@ while [[ $# -gt 0 ]]; do
|
|
|
137
141
|
shift
|
|
138
142
|
;;
|
|
139
143
|
--subagents-preset)
|
|
140
|
-
|
|
144
|
+
require_value "$1" "${2:-}"
|
|
145
|
+
SUBAGENTS_PRESET="$2"
|
|
141
146
|
shift 2
|
|
142
147
|
;;
|
|
143
148
|
--subagents-model-scope)
|
|
144
|
-
|
|
149
|
+
require_value "$1" "${2:-}"
|
|
150
|
+
SUBAGENTS_MODEL_SCOPE="$2"
|
|
145
151
|
shift 2
|
|
146
152
|
;;
|
|
147
153
|
--with-web-access)
|
|
@@ -157,11 +163,13 @@ while [[ $# -gt 0 ]]; do
|
|
|
157
163
|
shift
|
|
158
164
|
;;
|
|
159
165
|
--model-scope)
|
|
160
|
-
|
|
166
|
+
require_value "$1" "${2:-}"
|
|
167
|
+
MODEL_SCOPE_PRESET="$2"
|
|
161
168
|
shift 2
|
|
162
169
|
;;
|
|
163
170
|
--default-model)
|
|
164
|
-
|
|
171
|
+
require_value "$1" "${2:-}"
|
|
172
|
+
DEFAULT_MODEL="$2"
|
|
165
173
|
shift 2
|
|
166
174
|
;;
|
|
167
175
|
--no-model-scope)
|
|
@@ -39,16 +39,22 @@ todos, and project memory. Those are operator data, not platform state.
|
|
|
39
39
|
USAGE
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
require_value() {
|
|
43
|
+
local option="$1"
|
|
44
|
+
local value="${2:-}"
|
|
45
|
+
if [[ -z "$value" || "$value" == --* ]]; then
|
|
46
|
+
echo "Missing value for $option" >&2
|
|
47
|
+
exit 2
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
while [[ $# -gt 0 ]]; do
|
|
43
52
|
case "$1" in
|
|
44
53
|
--apply) APPLY=true; shift ;;
|
|
45
54
|
--with-addons) WITH_ADDONS=true; shift ;;
|
|
46
55
|
--with-host) WITH_HOST=true; shift ;;
|
|
47
56
|
--project)
|
|
48
|
-
|
|
49
|
-
echo "Missing value for --project" >&2
|
|
50
|
-
exit 2
|
|
51
|
-
fi
|
|
57
|
+
require_value "$1" "${2:-}"
|
|
52
58
|
PROJECT_PATH="$2"
|
|
53
59
|
shift 2
|
|
54
60
|
;;
|
package/scripts/verify-local.sh
CHANGED
|
@@ -164,6 +164,7 @@ required_files=(
|
|
|
164
164
|
"$ROOT/scripts/quality-benchmark.sh"
|
|
165
165
|
"$ROOT/scripts/runtime-policy-smoke.sh"
|
|
166
166
|
"$ROOT/scripts/pi-session-stats.sh"
|
|
167
|
+
"$ROOT/scripts/pi-usage-history.mjs"
|
|
167
168
|
"$ROOT/scripts/pi-auto.sh"
|
|
168
169
|
"$ROOT/scripts/pi-model-catalog.sh"
|
|
169
170
|
"$ROOT/scripts/configure-model-scope.sh"
|
|
@@ -469,6 +470,23 @@ require_documented "piagent-capabilities" "$ROOT/README.md" "$ROOT/docs/capabili
|
|
|
469
470
|
require_documented ".pi-subagents/" "$ROOT/.gitignore" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/docs/distribution-standard.md" "$ROOT/scripts/init-project.sh"
|
|
470
471
|
test -s "$ROOT/tests/policy-core.test.mjs"
|
|
471
472
|
|
|
473
|
+
# Every gate below this line is a grep, and grep skips a file it decides is
|
|
474
|
+
# binary. One control byte written into a string literal — a NUL used as a key
|
|
475
|
+
# separator is the easy way to do it by accident — takes the whole file out of
|
|
476
|
+
# every one of them, and out of the diff a reviewer reads on a pull request. The
|
|
477
|
+
# file still runs, so nothing else notices. Escapes carry the same bytes and keep
|
|
478
|
+
# the file readable.
|
|
479
|
+
non_text_sources="$(
|
|
480
|
+
cd "$ROOT" && git ls-files -z -- '*.js' '*.mjs' '*.ts' '*.json' '*.md' '*.sh' '*.html' '*.css' \
|
|
481
|
+
| LC_ALL=C xargs -0 -I{} sh -c 'grep -qI "" "{}" 2>/dev/null || echo "{}"'
|
|
482
|
+
)"
|
|
483
|
+
if [[ -n "$non_text_sources" ]]; then
|
|
484
|
+
echo "Source files contain control bytes, so grep-based gates and diffs skip them:"
|
|
485
|
+
echo "$non_text_sources" | sed 's/^/ /'
|
|
486
|
+
echo "Write the byte as an escape (\\u0000, \\x03) instead of embedding it."
|
|
487
|
+
exit 1
|
|
488
|
+
fi
|
|
489
|
+
|
|
472
490
|
public_wording_pattern="$(
|
|
473
491
|
node --input-type=module <<'NODE'
|
|
474
492
|
const terms = [
|
|
@@ -527,6 +545,7 @@ node --check "$ROOT/packages/piagent-core/capabilities/capability-core.js" >/dev
|
|
|
527
545
|
node --check "$ROOT/packages/piagent-core/capabilities/capability-sources.js" >/dev/null
|
|
528
546
|
node --check "$ROOT/scripts/capability-catalog.mjs" >/dev/null
|
|
529
547
|
node --check "$ROOT/scripts/piagent-cli.mjs" >/dev/null
|
|
548
|
+
node --check "$ROOT/scripts/pi-usage-history.mjs" >/dev/null
|
|
530
549
|
node --check "$ROOT/scripts/migrate-project-state.mjs" >/dev/null
|
|
531
550
|
node --check "$ROOT/scripts/import-agent-instructions.mjs" >/dev/null
|
|
532
551
|
node --check "$ROOT/scripts/check-runtime-advisories.mjs" >/dev/null
|
|
@@ -80,6 +80,35 @@ for (const page of docsPages) {
|
|
|
80
80
|
if (!html.includes(`${expectedTag} docs`)) fail(`docs-site/${page} version badge does not identify ${expectedTag}`);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
// A version written into an install command does not come from the build, so it
|
|
84
|
+
// goes stale silently and keeps telling readers to install the previous release.
|
|
85
|
+
// The badge check above cannot see these: they are sentences, not generated
|
|
86
|
+
// markup.
|
|
87
|
+
//
|
|
88
|
+
// Only the command shapes are matched, not every version-looking string. Prose
|
|
89
|
+
// naming an old release is usually saying something true about history — when a
|
|
90
|
+
// behaviour arrived, which release a mistake shipped in — and rewriting those to
|
|
91
|
+
// the current number would make them false. Files that exist to list past
|
|
92
|
+
// versions are exempt outright.
|
|
93
|
+
const VERSION_HISTORY_FILES = new Set(["CHANGELOG.md", "docs/publishing-for-teams.md"]);
|
|
94
|
+
const RELEASE_TAG_MENTION = /(?:@piagent\/platform@|Vt-mmm\/piagent@v?|--version )(\d+\.\d+\.\d+)/g;
|
|
95
|
+
|
|
96
|
+
function proseFiles() {
|
|
97
|
+
const files = fs.readdirSync(path.join(root, "docs")).filter((name) => name.endsWith(".md")).map((name) => `docs/${name}`);
|
|
98
|
+
files.push("README.md");
|
|
99
|
+
for (const name of fs.readdirSync(path.join(root, "docs-site", "content"))) {
|
|
100
|
+
if (name.endsWith(".html")) files.push(`docs-site/content/${name}`);
|
|
101
|
+
}
|
|
102
|
+
return files.filter((file) => !VERSION_HISTORY_FILES.has(file));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const file of proseFiles()) {
|
|
106
|
+
const text = fs.readFileSync(path.join(root, file), "utf8");
|
|
107
|
+
for (const [mention, named] of text.matchAll(RELEASE_TAG_MENTION)) {
|
|
108
|
+
if (named !== version) fail(`${file} tells the reader to install ${named} (${mention.trim()}), but this release is ${version}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
83
112
|
if (options.tag) {
|
|
84
113
|
if (options.tag !== expectedTag) fail(`release tag ${options.tag} does not match package version ${expectedTag}`);
|
|
85
114
|
if (!/^[0-9a-fA-F]{40}$/.test(options.commit)) fail("--commit must be a 40-character commit SHA");
|