newo 3.7.3 → 3.7.5
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 +35 -2
- package/README.md +71 -2
- package/dist/cli/commands/get-skill.d.ts +3 -0
- package/dist/cli/commands/get-skill.js +72 -0
- package/dist/cli/commands/help.js +29 -0
- package/dist/cli/commands/logs.d.ts +6 -1
- package/dist/cli/commands/logs.js +62 -14
- package/dist/cli/commands/sandbox.d.ts +10 -4
- package/dist/cli/commands/sandbox.js +182 -51
- package/dist/cli/commands/update-skill.d.ts +4 -0
- package/dist/cli/commands/update-skill.js +119 -0
- package/dist/cli.js +8 -0
- package/dist/domain/strategies/sync/V2ProjectSyncStrategy.d.ts +37 -0
- package/dist/domain/strategies/sync/V2ProjectSyncStrategy.js +383 -24
- package/dist/sandbox/chat.d.ts +23 -3
- package/dist/sandbox/chat.js +83 -30
- package/dist/sync/remote-skill.d.ts +33 -0
- package/dist/sync/remote-skill.js +52 -0
- package/package.json +1 -1
- package/src/cli/commands/get-skill.ts +84 -0
- package/src/cli/commands/help.ts +29 -0
- package/src/cli/commands/logs.ts +83 -15
- package/src/cli/commands/sandbox.ts +238 -60
- package/src/cli/commands/update-skill.ts +139 -0
- package/src/cli.ts +10 -0
- package/src/domain/strategies/sync/V2ProjectSyncStrategy.ts +530 -26
- package/src/sandbox/chat.ts +106 -29
- package/src/sync/remote-skill.ts +92 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.7.5] - 2026-06-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`newo sandbox` connector selection (R1)** — new `--connector <connector_idn>` and `--integration <idn>` flags select which connector to chat through instead of always taking the first running connector of the `sandbox` integration (which made agents like Vibe Builder's `vibe_agent` unreachable from the CLI when another connector, e.g. `convo_agent_sandbox`, came first). `--list-connectors` prints the running connectors (with `--json` for machine output). When `--connector` is not found, the error lists the available running connectors. Without flags, behavior is unchanged (first running connector). Surfaced during PR #2076 superagent testing.
|
|
15
|
+
- **`newo sandbox` long messages and machine-readable output (R2)** — `--file <path>` and `--stdin` send message text without shell-argument limits (tested scenarios used 40k–400k char messages); `--timeout <seconds>` overrides the previously hardcoded 60-second response-poll limit (long VibeFlow turns ran 1–7 minutes); `--json` emits `{actor_id, persona_id, connector_idn, external_event_id, user_external_event_id, agent_external_event_id, response, elapsed_ms, timed_out, flow_idn, skill_idn, session_id}`. The `external_event_id` of the user turn is the correlation key for `newo logs --event-id`, closing the gap that previously required ad-hoc scripts importing `dist/api.js` directly.
|
|
16
|
+
- **`newo get-skill` / `newo update-skill` (R3)** — point inspection and point edits of a single skill on the platform by IDN path (`<skill-idn> --project <idn> --agent <idn> --flow <idn>`), with no pulled workspace required. `get-skill` shows the live model, runner_type, parameters, and prompt_script (`--json` supported). `update-skill` changes `--model <provider_idn>/<model_idn>` and/or `--script <file>`, leaving everything else untouched; `--publish` (with optional `--publish-description`) publishes the flow afterwards, otherwise changes stay draft. Warns when a local pulled workspace exists and now diverges. Covers the "switch model → run test → switch back" scenario in two commands.
|
|
17
|
+
- **`newo logs --name <ActionName>` (R4)** — client-side filter on `data.name` (e.g. only `Gen` or `GetMemory` action calls), replacing `--json` + jq post-filtering. Help text now documents that the model of a turn must be read from `data.source.model` in `--json` output, not inferred from actor/agent names.
|
|
18
|
+
- **`newo logs --raw`** — JSONL output: one JSON object per log line (sorted oldest-first), with no banners or empty-result text, so stdout is a clean machine-readable stream for piping (`newo logs --raw | jq ...`). Distinct from `--json`, which emits a single pretty-printed JSON array.
|
|
19
|
+
- **`src/sync/remote-skill.ts`** — shared resolver (`resolveRemoteSkill`, `parseModelFlag`) that maps a project/agent/flow/skill IDN path to platform IDs with descriptive errors listing available IDNs at the failing level.
|
|
20
|
+
- **20 unit tests** — 14 in `test/sandbox-skill-commands.test.js` covering connector selection (legacy first-running behavior, exact match, non-running exclusion, error listings), poll timeout override, user/agent `external_event_id` capture, IDN-path resolution, and `--model` flag parsing, plus 6 in `test/logs-command.test.js` covering `--name` client-side filtering, pagination, and `--raw` JSONL output — all against a fake axios client, no network.
|
|
21
|
+
|
|
22
|
+
## [3.7.4] - 2026-06-10
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **V2 push now creates new skills from inline flow YAML definitions.** Previously the `newo_v2` push path could only update content of skills already known to the local project map; a skill added locally to `{FlowIdn}.yaml` after the last pull was silently ignored, leaving its `.nsl`/`.nslg` script with no way to reach the platform. `V2ProjectSyncStrategy.push()` now reconciles inline skill metadata before iterating script changes: missing remote skills are created via `POST /api/v1/designer/flows/{flowId}/skills`, race-condition duplicates (already-exists on create) fall back to fetching the remote skill via `listFlowSkills` and updating it, and missing skill parameters are filled in via `POST /api/v1/designer/flows/skills/{skillId}/parameters`. The local project map and SHA256 hash store are updated atomically after the reconciliation pass.
|
|
27
|
+
- **Strict model validation before V2 skill writes.** New `assertSkillModelResolved` helper throws a descriptive error ("Set either skill.model.* or flow default_model_idn/default_provider_idn") when neither the inline skill nor the flow declares a model/provider, instead of letting the platform return a generic 4xx with no hint about which YAML field is missing.
|
|
28
|
+
- **33 unit tests** in `test/v2-push-helpers.test.js` covering `isAlreadyExistsApiError`, `assertSkillModelResolved`, `normalizeRunnerType`, `normalizeParameters`, `skillMetadataDiffers`, `buildV2SkillMetadataFromYaml`, and `createMissingSkillParameters` (stubbed API client). Regression-locks the false-positive matcher fix, the model-validation contract, the parameter-creation counting, and the model-key-order false positive.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`isAlreadyExistsApiError` no longer matches "does not exist".** The previous detector accepted any 400/409/422 response whose body contained the substring `"exist"`, which incorrectly classified "Skill does not exist" / "Flow doesn't exist" errors as duplicates and triggered a spurious reuse fallback. The matcher is now tightened to only `"already exists"` and `"duplicate key"`.
|
|
33
|
+
- **`validate()` reports missing scripts for YAML-declared skills.** Previously `V2ProjectSyncStrategy.validate()` only checked scripts listed in the local map; skills added directly to `{FlowIdn}.yaml` since the last pull were never validated. Validation now walks the YAML when present and surfaces a `Script file not found:` error per skill, matching the new push contract.
|
|
34
|
+
- **Missing-script skills are reported, not silently skipped.** Instead of a `verbose`-only "Skipping skill without local script" log, the push now records `[newo_v2] Missing script for skill {project}/{agent}/{flow}/{skill}: {path}` in the push errors. Failures are isolated per skill: one broken skill no longer aborts the push of every other flow/project in the workspace.
|
|
35
|
+
- **Model validation only runs before actual platform writes.** `assertSkillModelResolved` fires only when a skill is about to be created or its metadata updated — a pre-existing flow YAML without `skill.model.*` / flow `default_model_idn` no longer blocks pushes of unrelated, untouched skills.
|
|
36
|
+
- **Parameter-creation count is no longer inflated by already-existing parameters.** `createMissingSkillParameters` incremented its counter (and logged "Created skill parameter") even when the platform answered "already exists", which spuriously triggered a follow-up `updateSkill` call. Count and log now happen only on successful creation.
|
|
37
|
+
- **`isAlreadyExistsApiError` no longer throws on `null`/`undefined` errors** (optional chaining on `.response`), which previously masked the original failure inside catch handlers.
|
|
38
|
+
- **`skillMetadataDiffers` no longer flags every skill as changed.** The model comparison used `JSON.stringify`, which is key-order-sensitive: the project map stores `{provider_idn, model_idn}` (platform API order) while YAML-built metadata uses `{model_idn, provider_idn}`. Verified against a live account: every push rewrote all 1342 skills. Model is now compared field-by-field and parameters are compared order-insensitively (sorted by name).
|
|
39
|
+
- **Skill parameters are now created explicitly after `createSkill`.** The platform's create endpoint ignores inline `parameters` in the request body (verified against the live platform) — newly created skills silently lost their YAML-declared parameters. The create path now calls `POST /flows/skills/{skillId}/parameters` per parameter, same as the update path.
|
|
40
|
+
|
|
10
41
|
## [3.7.3] - 2026-05-25
|
|
11
42
|
|
|
12
43
|
### Fixed
|
|
@@ -1061,7 +1092,9 @@ Another Item: $Price [Modifiers: modifier3]
|
|
|
1061
1092
|
- GitHub Actions CI/CD integration
|
|
1062
1093
|
- Robust authentication with token refresh
|
|
1063
1094
|
|
|
1064
|
-
[Unreleased]: https://github.com/sabbah13/newo-cli/compare/v3.7.
|
|
1095
|
+
[Unreleased]: https://github.com/sabbah13/newo-cli/compare/v3.7.5...HEAD
|
|
1096
|
+
[3.7.5]: https://github.com/sabbah13/newo-cli/compare/v3.7.4...v3.7.5
|
|
1097
|
+
[3.7.4]: https://github.com/sabbah13/newo-cli/compare/v3.7.3...v3.7.4
|
|
1065
1098
|
[3.7.3]: https://github.com/sabbah13/newo-cli/compare/v3.7.2...v3.7.3
|
|
1066
1099
|
[3.7.2]: https://github.com/sabbah13/newo-cli/compare/v3.7.1...v3.7.2
|
|
1067
1100
|
[3.7.1]: https://github.com/sabbah13/newo-cli/compare/v3.7.0...v3.7.1
|
|
@@ -1095,4 +1128,4 @@ Another Item: $Price [Modifiers: modifier3]
|
|
|
1095
1128
|
[1.4.0]: https://github.com/sabbah13/newo-cli/compare/v1.2.1...v1.4.0
|
|
1096
1129
|
[1.3.0]: https://github.com/sabbah13/newo-cli/compare/v1.2.1...v1.3.0
|
|
1097
1130
|
[1.2.2]: https://github.com/sabbah13/newo-cli/compare/v1.2.1...v1.2.2
|
|
1098
|
-
[1.2.1]: https://github.com/sabbah13/newo-cli/releases/tag/v1.2.1
|
|
1131
|
+
[1.2.1]: https://github.com/sabbah13/newo-cli/releases/tag/v1.2.1
|
package/README.md
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
**NEWO CLI** - Professional command-line tool for NEWO AI Agent development. Features **modular architecture**, **IDN-based file management**, and **comprehensive multi-customer support**.
|
|
9
9
|
|
|
10
10
|
Sync NEWO "Project → Agent → Flow → Skills" structure to local files with:
|
|
11
|
+
- 🆕 **V2 skill creation on push** (v3.7.4) - adding a skill inline to a `newo_v2` `{FlowIdn}.yaml` and pushing now creates it on the platform (previously only updates of existing skills worked)
|
|
12
|
+
- 🆕 **Sandbox connector selection + automation** (v3.7.5) - `newo sandbox --connector <idn>`, `--list-connectors`, `--file`/`--stdin` for long messages, `--timeout`, and `--json` with `external_event_id` for log correlation
|
|
13
|
+
- 🆕 **Point skill edits** (v3.7.5) - `newo get-skill` / `newo update-skill` inspect and modify a single skill (model, script) on the platform without a pulled workspace, with optional `--publish`
|
|
11
14
|
- 🆕 **Canvas blank-screen hardening** (v3.7.3) - JSON-typed attributes (e.g. Workflow Builder canvas) with Markdown `\_` escapes or structural newlines no longer corrupt the canvas on push ([#7](https://github.com/sabbah13/newo-cli/pull/7))
|
|
12
15
|
- 🆕 **Flow metadata sync** (v3.7.2) - `newo push` now reconciles flow title, events, and state_fields from local `metadata.yaml` to the platform (closes [#3](https://github.com/sabbah13/newo-cli/issues/3))
|
|
13
16
|
- 🆕 **Dual format support** (v3.6.0) - `cli_v1` (native) and `newo_v2` (platform compatible), auto-detected per customer
|
|
@@ -149,12 +152,78 @@ NEWO_REFRESH_URL=custom_refresh_endpoint # Custom refresh endpoint
|
|
|
149
152
|
| `newo push [--format <fmt>]` | Upload local changes to NEWO | • Works with both formats<br>• Hash-based change detection<br>• Library skill updates<br>• Publishes flows automatically |
|
|
150
153
|
| `newo status [--format <fmt>]` | Show modified files | • Format-aware status<br>• Multiple file warnings<br>• Per-customer status |
|
|
151
154
|
| `newo export [--output <file>]` | Download V2 bulk ZIP from platform | • Complete organization export<br>• Projects, agents, flows, skills, attributes, AKB<br>• Compatible with platform UI import |
|
|
152
|
-
| `newo sandbox` | Test agents in sandbox chat mode | • Single-command mode for automation<br>• Multi-turn conversation support<br>• Debug info for agent development |
|
|
155
|
+
| `newo sandbox` | Test agents in sandbox chat mode | • Single-command mode for automation<br>• Multi-turn conversation support<br>• Debug info for agent development<br>• v3.7.5: `--connector`, `--list-connectors`, `--file`/`--stdin`, `--timeout`, `--json` |
|
|
156
|
+
| `newo get-skill` / `newo update-skill` | Inspect / point-edit one skill on the platform (NEW v3.7.5) | • No pulled workspace required<br>• `--model <provider>/<model>`, `--script <file>`<br>• Optional `--publish` |
|
|
153
157
|
| `newo conversations` | Pull conversation history | • User personas and chat history<br>• YAML format output<br>• Pagination support |
|
|
154
158
|
| `newo list-customers` | List configured customers | • Shows default customer<br>• Multi-customer discovery |
|
|
155
159
|
| `newo import-akb` | Import knowledge base articles | • Structured text parsing<br>• Bulk article import<br>• Validation and error reporting |
|
|
156
160
|
| `newo meta` | Get project metadata (debug) | • Project structure analysis<br>• Metadata validation |
|
|
157
161
|
|
|
162
|
+
### Sandbox Connector Selection & Automation (NEW v3.7.5)
|
|
163
|
+
|
|
164
|
+
`newo sandbox` previously always chatted through the **first** running connector of the `sandbox` integration, making other agents (e.g. a Vibe Builder behind a `vibe_agent` connector) unreachable from the CLI. v3.7.5 adds connector selection plus automation-friendly I/O:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
newo sandbox --list-connectors # show running sandbox connectors
|
|
168
|
+
newo sandbox "ping" --connector vibe_agent # chat through a specific connector
|
|
169
|
+
newo sandbox "ping" --integration sandbox --connector vibe_agent # explicit pair (default integration: sandbox)
|
|
170
|
+
|
|
171
|
+
newo sandbox --file ./chunk1.txt --actor <id> --json # long message from file, machine-readable output
|
|
172
|
+
cat chunk1.txt | newo sandbox --stdin --actor <id> # message from stdin
|
|
173
|
+
newo sandbox "ping" --timeout 420 # wait up to 7 minutes for slow agent turns (default: 60s)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`--json` output includes the correlation keys for `newo logs`:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"actor_id": "…", "persona_id": "…", "connector_idn": "vibe_agent",
|
|
181
|
+
"external_event_id": "…", // user turn — use with: newo logs --event-id <id>
|
|
182
|
+
"user_external_event_id": "…", "agent_external_event_id": "…",
|
|
183
|
+
"response": "…", "elapsed_ms": 12345, "timed_out": false,
|
|
184
|
+
"flow_idn": "VibeFlow", "skill_idn": "…", "session_id": "…"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Without `--connector`, behavior is unchanged (first running connector), so existing scripts keep working. When the requested connector is missing, the error lists the available running connectors.
|
|
189
|
+
|
|
190
|
+
This makes agent integration tests scriptable in plain bash: send chunks via `newo sandbox --file … --json`, then verify behavior via `newo logs --event-id … --json` — no more ad-hoc Node scripts importing `dist/api.js`.
|
|
191
|
+
|
|
192
|
+
### Point Skill Inspection & Edits (NEW v3.7.5)
|
|
193
|
+
|
|
194
|
+
Inspect or modify a **single skill** directly on the platform by IDN path — no pulled `newo_customers/` workspace required, nothing else gets touched:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# What lives on the platform right now? (model, runner_type, parameters, prompt_script)
|
|
198
|
+
newo get-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow [--json]
|
|
199
|
+
|
|
200
|
+
# Temporarily switch a model, publish, run tests, switch back:
|
|
201
|
+
newo update-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow \
|
|
202
|
+
--model google/gemini25_pro --publish
|
|
203
|
+
# …run your tests…
|
|
204
|
+
newo update-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow \
|
|
205
|
+
--model openai/gpt54 --publish
|
|
206
|
+
|
|
207
|
+
# Replace a skill script from a file (draft only, without --publish):
|
|
208
|
+
newo update-skill get_memory --project vibe --agent VibeAgent --flow VibeFlow --script ./patched.nsl
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
- `--model <provider_idn>/<model_idn>` and `--script <file>` can be combined; everything else (title, parameters, runner) is preserved.
|
|
212
|
+
- `--publish` publishes the flow after the update (same as push); without it the change stays draft. `--publish-description "<text>"` sets the publish note.
|
|
213
|
+
- If a pulled local workspace exists for the project, the CLI warns that it now diverges from the platform.
|
|
214
|
+
|
|
215
|
+
### Logs: Action-Name Filter (NEW v3.7.5)
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
newo logs --type call --name Gen --json # only Gen action calls
|
|
219
|
+
newo logs --name GetMemory --hours 24 # only GetMemory calls, last 24h
|
|
220
|
+
newo logs --type call --raw | jq '.data.name' # JSONL stream, one log per line, for piping
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`--name` filters by `data.name` client-side (the API has no such query param). Note: the **model used for a turn** is in `data.source.model` of the `--json` output — do not infer it from actor/agent names.
|
|
224
|
+
|
|
225
|
+
`--raw` emits **JSONL** — one JSON object per log line (oldest-first), with no banners or "no logs found" text — so stdout is a clean stream for `jq`/piping. This differs from `--json`, which prints a single pretty-printed JSON array.
|
|
226
|
+
|
|
158
227
|
### Flow Metadata Sync (NEW v3.7.2)
|
|
159
228
|
|
|
160
229
|
`newo push` now reconciles **flow-level metadata** — title, `events:`, and `state_fields:` — from local YAML to the platform. Before v3.7.2 push only uploaded skill scripts, so edits to a flow's `metadata.yaml` (V1) or `{FlowIdn}.yaml` (V2) silently never reached the platform; events added via `newo create-event` could appear to disappear after a pull → push cycle. Closes [#3](https://github.com/sabbah13/newo-cli/issues/3).
|
|
@@ -1378,4 +1447,4 @@ NEWO CLI integrates with these NEWO platform endpoints:
|
|
|
1378
1447
|
|
|
1379
1448
|
---
|
|
1380
1449
|
|
|
1381
|
-
**Built with ❤️ by the NEWO team**
|
|
1450
|
+
**Built with ❤️ by the NEWO team**
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get Skill Command Handler - Inspect a skill's live state on the platform
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* newo get-skill <skill-idn> --project <idn> --agent <idn> --flow <idn> [--json]
|
|
6
|
+
*
|
|
7
|
+
* Shows the skill as it currently lives on the platform (model, runner_type,
|
|
8
|
+
* parameters, prompt_script) without requiring a pulled local workspace.
|
|
9
|
+
*/
|
|
10
|
+
import { requireSingleCustomer } from '../customer-selection.js';
|
|
11
|
+
import { makeClient } from '../../api.js';
|
|
12
|
+
import { getValidAccessToken } from '../../auth.js';
|
|
13
|
+
import { resolveRemoteSkill } from '../../sync/remote-skill.js';
|
|
14
|
+
const USAGE = 'Usage: newo get-skill <skill-idn> --project <project-idn> --agent <agent-idn> --flow <flow-idn> [--json] [--customer <idn>]';
|
|
15
|
+
export async function handleGetSkillCommand(customerConfig, args, verbose = false) {
|
|
16
|
+
const skillIdn = args._[1];
|
|
17
|
+
const projectIdn = args.project;
|
|
18
|
+
const agentIdn = args.agent;
|
|
19
|
+
const flowIdn = args.flow;
|
|
20
|
+
const asJson = Boolean(args.json);
|
|
21
|
+
if (!skillIdn || !projectIdn || !agentIdn || !flowIdn) {
|
|
22
|
+
console.error('Error: skill IDN, --project, --agent and --flow are required');
|
|
23
|
+
console.error(USAGE);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const selectedCustomer = requireSingleCustomer(customerConfig, args.customer);
|
|
27
|
+
if (asJson) {
|
|
28
|
+
process.env.NEWO_QUIET_MODE = 'true'; // keep stdout machine-readable for piping
|
|
29
|
+
}
|
|
30
|
+
const token = await getValidAccessToken(selectedCustomer);
|
|
31
|
+
const client = await makeClient(verbose, token);
|
|
32
|
+
if (verbose)
|
|
33
|
+
console.log(`🔍 Resolving skill ${projectIdn}/${agentIdn}/${flowIdn}/${skillIdn}...`);
|
|
34
|
+
const { project, agent, flow, skill } = await resolveRemoteSkill(client, {
|
|
35
|
+
projectIdn,
|
|
36
|
+
agentIdn,
|
|
37
|
+
flowIdn,
|
|
38
|
+
skillIdn
|
|
39
|
+
});
|
|
40
|
+
if (asJson) {
|
|
41
|
+
console.log(JSON.stringify({
|
|
42
|
+
project_idn: project.idn,
|
|
43
|
+
agent_idn: agent.idn,
|
|
44
|
+
flow_idn: flow.idn,
|
|
45
|
+
id: skill.id,
|
|
46
|
+
idn: skill.idn,
|
|
47
|
+
title: skill.title,
|
|
48
|
+
runner_type: skill.runner_type,
|
|
49
|
+
model: skill.model,
|
|
50
|
+
parameters: skill.parameters,
|
|
51
|
+
prompt_script: skill.prompt_script ?? null
|
|
52
|
+
}, null, 2));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log(`📜 Skill: ${project.idn}/${agent.idn}/${flow.idn}/${skill.idn}`);
|
|
56
|
+
console.log(` ID: ${skill.id}`);
|
|
57
|
+
console.log(` Title: ${skill.title}`);
|
|
58
|
+
console.log(` Runner type: ${skill.runner_type}`);
|
|
59
|
+
console.log(` Model: ${skill.model.provider_idn}/${skill.model.model_idn}`);
|
|
60
|
+
if (skill.parameters.length > 0) {
|
|
61
|
+
console.log(` Parameters:`);
|
|
62
|
+
for (const param of skill.parameters) {
|
|
63
|
+
console.log(` ${param.name}${param.default_value !== undefined ? ` = ${JSON.stringify(param.default_value)}` : ''}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(` Parameters: (none)`);
|
|
68
|
+
}
|
|
69
|
+
console.log(`\n--- prompt_script (${(skill.prompt_script || '').length} chars) ---`);
|
|
70
|
+
console.log(skill.prompt_script || '(empty)');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=get-skill.js.map
|
|
@@ -16,6 +16,11 @@ Core Commands:
|
|
|
16
16
|
newo conversations [--customer <idn>] [--all] # download user conversations -> conversations.yaml
|
|
17
17
|
newo sandbox "<message>" [--customer <idn>] # test agent in sandbox - single message mode
|
|
18
18
|
newo sandbox --actor <id> "message" # continue existing sandbox conversation
|
|
19
|
+
newo sandbox --list-connectors # list running sandbox connectors (NEW v3.7.5)
|
|
20
|
+
newo sandbox "<msg>" --connector <idn> # chat through a specific connector (NEW v3.7.5)
|
|
21
|
+
newo sandbox --file <path> | --stdin # send long messages from file/stdin (NEW v3.7.5)
|
|
22
|
+
newo get-skill <idn> --project <p> --agent <a> --flow <f> [--json] # inspect live skill on platform (NEW v3.7.5)
|
|
23
|
+
newo update-skill <idn> --project <p> --agent <a> --flow <f> [--model <prov>/<model>] [--script <file>] [--publish] # point-edit skill (NEW v3.7.5)
|
|
19
24
|
newo pull-attributes [--customer <idn>] # download customer + project attributes
|
|
20
25
|
newo list-customers # list available customers
|
|
21
26
|
newo meta [--customer <idn>] # get project metadata (debug)
|
|
@@ -76,6 +81,8 @@ Analytics & Monitoring (NEW):
|
|
|
76
81
|
newo logs --type <types> # filter by type: system, operation, call (comma-separated)
|
|
77
82
|
newo logs --flow <idn> --skill <idn> # filter by flow and/or skill
|
|
78
83
|
newo logs --message <text> # search in log messages
|
|
84
|
+
newo logs --name <ActionName> # filter by action name in data.name, e.g. Gen, GetMemory (NEW v3.7.5)
|
|
85
|
+
newo logs --event-id <uuid> # filter by external event ID (correlate with sandbox --json)
|
|
79
86
|
newo logs --follow, -f # tail mode - continuously poll for new logs
|
|
80
87
|
newo logs --json # output logs as JSON array
|
|
81
88
|
newo logs --raw # output each log as single JSON line (for piping)
|
|
@@ -94,6 +101,12 @@ Flags:
|
|
|
94
101
|
--verbose, -v # enable detailed logging and progress information
|
|
95
102
|
--quiet, -q # minimal output for automation (sandbox only)
|
|
96
103
|
--actor <id> # continue existing sandbox chat with actor/chat ID
|
|
104
|
+
--connector <idn> # sandbox: select connector by connector_idn (default: first running)
|
|
105
|
+
--integration <idn> # sandbox: integration to search connectors in (default: sandbox)
|
|
106
|
+
--file <path> # sandbox: read message text from file
|
|
107
|
+
--stdin # sandbox: read message text from stdin
|
|
108
|
+
--timeout <seconds> # sandbox: max wait for agent response (default: 60)
|
|
109
|
+
--json # sandbox: machine-readable output incl. external_event_id (user+agent turns)
|
|
97
110
|
--confirm # confirm destructive operations without prompting
|
|
98
111
|
--no-publish # skip automatic flow publishing during push operations
|
|
99
112
|
--output, -o <file> # output file path (for export command)
|
|
@@ -201,6 +214,22 @@ Usage Examples:
|
|
|
201
214
|
newo sandbox "Test query" --verbose # With debug info
|
|
202
215
|
newo sandbox "Test query" --quiet # For automation/scripts
|
|
203
216
|
|
|
217
|
+
# Sandbox connector selection + automation (NEW v3.7.5):
|
|
218
|
+
newo sandbox --list-connectors # Show running sandbox connectors
|
|
219
|
+
newo sandbox "ping" --connector vibe_agent # Chat through specific connector
|
|
220
|
+
newo sandbox --file ./chunk1.txt --actor abc123... --json # Long message from file, JSON output
|
|
221
|
+
cat msg.txt | newo sandbox --stdin --timeout 420 --json # From stdin with 7-minute timeout
|
|
222
|
+
# --json output: {actor_id, persona_id, external_event_id, user_external_event_id,
|
|
223
|
+
# agent_external_event_id, response, elapsed_ms, timed_out, ...}
|
|
224
|
+
# Correlate a turn with its logs: newo logs --event-id <external_event_id> --json
|
|
225
|
+
|
|
226
|
+
# Live skill inspection / point edits (NEW v3.7.5):
|
|
227
|
+
newo get-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow # View live state
|
|
228
|
+
newo get-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow --json # As JSON
|
|
229
|
+
newo update-skill structured_generation --project vibe --agent VibeAgent --flow VibeFlow \\
|
|
230
|
+
--model openai/gpt54 --publish # Switch model and publish
|
|
231
|
+
newo update-skill my_skill --project p --agent a --flow f --script ./patched.nsl --publish # Replace script
|
|
232
|
+
|
|
204
233
|
# Analytics logs (NEW v3.5.0):
|
|
205
234
|
newo logs # Last 1 hour of logs
|
|
206
235
|
newo logs --hours 24 # Last 24 hours
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
* newo logs --follow # Tail mode (poll for new logs)
|
|
13
13
|
* newo logs --json # Output as JSON
|
|
14
14
|
*/
|
|
15
|
-
import type {
|
|
15
|
+
import type { AxiosInstance } from 'axios';
|
|
16
|
+
import type { MultiCustomerConfig, LogEntry, LogsQueryParams, LogsResponse, CliArgs } from '../../types.js';
|
|
17
|
+
type GetLogsFn = (client: AxiosInstance, params: LogsQueryParams) => Promise<LogsResponse>;
|
|
16
18
|
export declare function handleLogsCommand(customerConfig: MultiCustomerConfig, args: CliArgs, verbose: boolean): Promise<void>;
|
|
19
|
+
export declare function collectLogsForDisplay(client: AxiosInstance, params: LogsQueryParams, nameFilter?: string | null, getLogsFn?: GetLogsFn): Promise<LogEntry[]>;
|
|
20
|
+
export declare function fetchAndDisplayLogs(client: AxiosInstance, params: LogsQueryParams, asJson: boolean, raw: boolean, nameFilter?: string | null, getLogsFn?: GetLogsFn): Promise<void>;
|
|
17
21
|
export declare function printLogsHelp(): void;
|
|
22
|
+
export {};
|
|
18
23
|
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -85,7 +85,14 @@ function formatLogEntryCompact(log, showColors = true) {
|
|
|
85
85
|
export async function handleLogsCommand(customerConfig, args, verbose) {
|
|
86
86
|
// Select customer
|
|
87
87
|
const selectedCustomer = requireSingleCustomer(customerConfig, args.customer);
|
|
88
|
-
|
|
88
|
+
// Keep stdout machine-readable when JSON output is requested (for piping to jq etc.)
|
|
89
|
+
const machineOutput = Boolean(args.json || args.raw);
|
|
90
|
+
if (machineOutput) {
|
|
91
|
+
process.env.NEWO_QUIET_MODE = 'true'; // suppress auth logging on stdout
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(`📊 Fetching logs for ${selectedCustomer.idn}...`);
|
|
95
|
+
}
|
|
89
96
|
// Get access token and create client
|
|
90
97
|
const token = await getValidAccessToken(selectedCustomer);
|
|
91
98
|
const client = await makeClient(verbose, token);
|
|
@@ -146,21 +153,59 @@ export async function handleLogsCommand(customerConfig, args, verbose) {
|
|
|
146
153
|
const follow = Boolean(args.follow || args.f);
|
|
147
154
|
const asJson = Boolean(args.json);
|
|
148
155
|
const raw = Boolean(args.raw);
|
|
156
|
+
// --name filters by data.name (e.g. action name like Gen or GetMemory).
|
|
157
|
+
// The API has no such query param, so it is applied client-side.
|
|
158
|
+
const nameFilter = args.name ? String(args.name) : null;
|
|
149
159
|
if (follow) {
|
|
150
|
-
await tailLogs(client, params, asJson);
|
|
160
|
+
await tailLogs(client, params, asJson, nameFilter);
|
|
151
161
|
}
|
|
152
162
|
else {
|
|
153
|
-
await fetchAndDisplayLogs(client, params, asJson, raw);
|
|
163
|
+
await fetchAndDisplayLogs(client, params, asJson, raw, nameFilter);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function filterByName(logs, nameFilter) {
|
|
167
|
+
if (!nameFilter)
|
|
168
|
+
return [...logs];
|
|
169
|
+
return logs.filter(log => log.data['name'] === nameFilter);
|
|
170
|
+
}
|
|
171
|
+
export async function collectLogsForDisplay(client, params, nameFilter = null, getLogsFn = getLogs) {
|
|
172
|
+
if (!nameFilter) {
|
|
173
|
+
const response = await getLogsFn(client, params);
|
|
174
|
+
return [...response.items];
|
|
175
|
+
}
|
|
176
|
+
const pageSize = Number.isFinite(params.per) && params.per && params.per > 0 ? params.per : 50;
|
|
177
|
+
let page = Number.isFinite(params.page) && params.page && params.page > 0 ? params.page : 1;
|
|
178
|
+
const logs = [];
|
|
179
|
+
while (true) {
|
|
180
|
+
const response = await getLogsFn(client, {
|
|
181
|
+
...params,
|
|
182
|
+
page,
|
|
183
|
+
per: pageSize
|
|
184
|
+
});
|
|
185
|
+
logs.push(...filterByName(response.items, nameFilter));
|
|
186
|
+
if (response.items.length < pageSize) {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
page++;
|
|
154
190
|
}
|
|
191
|
+
return logs;
|
|
155
192
|
}
|
|
156
|
-
async function fetchAndDisplayLogs(client, params, asJson, raw) {
|
|
193
|
+
export async function fetchAndDisplayLogs(client, params, asJson, raw, nameFilter = null, getLogsFn = getLogs) {
|
|
157
194
|
try {
|
|
158
|
-
const
|
|
159
|
-
const logs = response.items;
|
|
195
|
+
const logs = await collectLogsForDisplay(client, params, nameFilter, getLogsFn);
|
|
160
196
|
if (asJson) {
|
|
161
197
|
console.log(JSON.stringify(logs, null, 2));
|
|
162
198
|
return;
|
|
163
199
|
}
|
|
200
|
+
// --raw is a machine-readable JSONL contract: stdout must contain only
|
|
201
|
+
// one JSON object per log line, with no banners or empty-result text.
|
|
202
|
+
if (raw) {
|
|
203
|
+
const sortedLogs = [...logs].sort((a, b) => new Date(a.datetime).getTime() - new Date(b.datetime).getTime());
|
|
204
|
+
for (const log of sortedLogs) {
|
|
205
|
+
console.log(JSON.stringify(log));
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
164
209
|
if (logs.length === 0) {
|
|
165
210
|
console.log('\nNo logs found for the specified criteria.');
|
|
166
211
|
return;
|
|
@@ -171,12 +216,7 @@ async function fetchAndDisplayLogs(client, params, asJson, raw) {
|
|
|
171
216
|
// Detect if stdout is a TTY (supports colors)
|
|
172
217
|
const useColors = process.stdout.isTTY !== false;
|
|
173
218
|
for (const log of sortedLogs) {
|
|
174
|
-
|
|
175
|
-
console.log(JSON.stringify(log));
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
console.log(formatLogEntry(log, useColors));
|
|
179
|
-
}
|
|
219
|
+
console.log(formatLogEntry(log, useColors));
|
|
180
220
|
}
|
|
181
221
|
console.log(`\n✅ Displayed ${logs.length} log entries`);
|
|
182
222
|
}
|
|
@@ -185,7 +225,7 @@ async function fetchAndDisplayLogs(client, params, asJson, raw) {
|
|
|
185
225
|
console.error('Failed to fetch logs:', err.response?.status, err.response?.data || err.message);
|
|
186
226
|
}
|
|
187
227
|
}
|
|
188
|
-
async function tailLogs(client, params, asJson) {
|
|
228
|
+
async function tailLogs(client, params, asJson, nameFilter = null) {
|
|
189
229
|
console.log('🔄 Watching for new logs (Ctrl+C to stop)...\n');
|
|
190
230
|
const seenLogIds = new Set();
|
|
191
231
|
let lastCheckTime = params.from_datetime || new Date(Date.now() - 60 * 60 * 1000).toISOString();
|
|
@@ -201,7 +241,7 @@ async function tailLogs(client, params, asJson) {
|
|
|
201
241
|
per: 100
|
|
202
242
|
};
|
|
203
243
|
const response = await getLogs(client, pollParams);
|
|
204
|
-
const logs = response.items;
|
|
244
|
+
const logs = filterByName(response.items, nameFilter);
|
|
205
245
|
// Filter out already seen logs and sort by time
|
|
206
246
|
const newLogs = logs
|
|
207
247
|
.filter(log => !seenLogIds.has(log.log_id))
|
|
@@ -257,6 +297,7 @@ Filter Options:
|
|
|
257
297
|
--flow <idn> Filter by flow IDN
|
|
258
298
|
--skill <idn> Filter by skill IDN
|
|
259
299
|
--message <text> Search in log messages
|
|
300
|
+
--name <ActionName> Filter by action name in data.name, e.g. Gen, GetMemory (client-side)
|
|
260
301
|
--event-id <uuid> Filter by external event ID
|
|
261
302
|
--runtime-id <uuid> Filter by runtime context ID
|
|
262
303
|
--actor-id <uuid> Filter by user actor ID
|
|
@@ -278,6 +319,13 @@ Examples:
|
|
|
278
319
|
newo logs --type call --skill CreateActor # Skill calls for CreateActor
|
|
279
320
|
newo logs --flow CACreatorFlow --follow # Tail logs for specific flow
|
|
280
321
|
newo logs --json --per 100 # Get 100 logs as JSON
|
|
322
|
+
newo logs --type call --name Gen --json # Only Gen action calls
|
|
323
|
+
|
|
324
|
+
Notes:
|
|
325
|
+
The model used for a turn is in data.source.model of the --json output —
|
|
326
|
+
do NOT infer it from actor/agent names.
|
|
327
|
+
external_event_id (newo sandbox --json) correlates a chat turn with its
|
|
328
|
+
logs: newo logs --event-id <id>
|
|
281
329
|
`);
|
|
282
330
|
}
|
|
283
331
|
//# sourceMappingURL=logs.js.map
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sandbox Chat Command Handler
|
|
3
3
|
* Supports both single-command and interactive modes
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx newo sandbox "Hello" --customer <idn> # Single message mode
|
|
7
|
+
* npx newo sandbox --actor <actor_id> "Follow up" # Continue existing chat
|
|
8
|
+
* npx newo sandbox "ping" --connector vibe_agent # Select specific connector (v3.7.5)
|
|
9
|
+
* npx newo sandbox --list-connectors # Show running sandbox connectors (v3.7.5)
|
|
10
|
+
* npx newo sandbox --file ./msg.txt --actor <id> # Message from file (v3.7.5)
|
|
11
|
+
* cat msg.txt | npx newo sandbox --stdin # Message from stdin (v3.7.5)
|
|
12
|
+
* npx newo sandbox "ping" --timeout 420 # Custom response timeout in seconds (v3.7.5)
|
|
13
|
+
* npx newo sandbox "ping" --json # Machine-readable output (v3.7.5)
|
|
4
14
|
*/
|
|
5
15
|
import type { MultiCustomerConfig, CliArgs } from '../../types.js';
|
|
6
16
|
/**
|
|
7
17
|
* Handle sandbox command
|
|
8
|
-
* Usage:
|
|
9
|
-
* npx newo sandbox "Hello" --customer <idn> # Single message mode
|
|
10
|
-
* npx newo sandbox --actor <actor_id> "Follow up" # Continue existing chat
|
|
11
|
-
* npx newo sandbox --interactive # Interactive mode (TBD)
|
|
12
18
|
*/
|
|
13
19
|
export declare function handleSandboxCommand(customerConfig: MultiCustomerConfig, args: CliArgs, verbose: boolean): Promise<void>;
|
|
14
20
|
//# sourceMappingURL=sandbox.d.ts.map
|