@phreshos/cli 0.1.69 → 0.1.71

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.
@@ -6,6 +6,7 @@ import windowCommands from "./window.js";
6
6
  import executeCommand from "./execute.js";
7
7
  import operationCommands from "./operation.js";
8
8
  import serviceCommands from "./service.js";
9
+ import systemCommands from "./system.js";
9
10
  /** Expose the shared System domains through explicit Node SDK executors. */
10
11
  export default function accessCommands(program, connect = connectSystem) {
11
12
  executeCommand(program, connect);
@@ -14,5 +15,6 @@ export default function accessCommands(program, connect = connectSystem) {
14
15
  processCommands(program, connect);
15
16
  endpointCommands(program, connect);
16
17
  serviceCommands(program, connect);
18
+ systemCommands(program, connect);
17
19
  windowCommands(program, connect);
18
20
  }
@@ -3,6 +3,7 @@ import { describeExecuteOperation } from "@phreshos/core";
3
3
  export const executeCommandPaths = Object.freeze({
4
4
  "operation.list": ["operation", "list"],
5
5
  "operation.describe": ["operation", "describe"],
6
+ "system.logs": ["system", "logs"],
6
7
  "program.list": ["program", "list"],
7
8
  "program.find": ["program", "inspect"],
8
9
  "program.agent": ["program", "agent"],
@@ -18,7 +19,6 @@ export const executeCommandPaths = Object.freeze({
18
19
  "program.allowsPermission": ["program", "allowsPermission"],
19
20
  "program.allowPermission": ["program", "allowPermission"],
20
21
  "program.denyPermission": ["program", "denyPermission"],
21
- "program.requestPermission": ["program", "requestPermission"],
22
22
  "program.logs": ["program", "logs"],
23
23
  "program.wait": ["program", "wait"],
24
24
  "process.list": ["process", "list"],
@@ -52,8 +52,6 @@ export const executeCommandPaths = Object.freeze({
52
52
  "window.maximize": ["window", "maximize"],
53
53
  "window.setTitle": ["window", "setTitle"],
54
54
  "window.setHeader": ["window", "setHeader"],
55
- "window.setSurface": ["window", "setSurface"],
56
- "window.setTransaction": ["window", "setTransaction"],
57
55
  "window.raise": ["window", "raise"],
58
56
  "window.wait": ["window", "wait"]
59
57
  });
@@ -196,22 +196,6 @@ export default function programCommands(root, connect) {
196
196
  identity: options.program,
197
197
  permission: parsePermissionName(options.permission)
198
198
  })));
199
- defineCommand(programs, {
200
- name: "requestPermission",
201
- aliases: ["request-permission"],
202
- description: executeDescription("program", "requestPermission"),
203
- requiresSystem: true,
204
- options: withJson(option("--program <identity>", "Program identity", { mandatory: true }), option("--permission <name>", "permission name", { mandatory: true }), option("--value <json>", "complete requested permission value encoded as JSON"), timeoutOption),
205
- output: dataOutput(value.any("permission decision"), "The permission decision", { format: "value" }),
206
- examples: ["phresh program request-permission --program terminal --permission uploads"]
207
- }, ({ options }) => connected(connect, system => system.execute({
208
- $domain: "program",
209
- $operation: "requestPermission",
210
- identity: options.program,
211
- permission: parsePermissionName(options.permission),
212
- ...(options.value === undefined ? {} : { value: permissionRequest(options.value) }),
213
- ...(options.timeout === undefined ? {} : { timeout: bounded(options.timeout, "--timeout", 0) })
214
- })));
215
199
  defineCommand(programs, {
216
200
  name: "logs",
217
201
  description: executeDescription("program", "logs"),
@@ -3,38 +3,6 @@ import { value } from "../contract/schema.js";
3
3
  const metric = {
4
4
  anyOf: [value.number("pixels"), value.string("workspace-relative expression")]
5
5
  };
6
- const transaction = {
7
- anyOf: [
8
- value.boolean("default or disabled transaction"),
9
- value.number("duration in milliseconds"),
10
- value.object({
11
- duration: value.number("duration in milliseconds"),
12
- easing: value.any("CSS easing name or cubic Bézier tuple")
13
- }, ["duration", "easing"], "appearance transaction")
14
- ]
15
- };
16
- const surface = {
17
- anyOf: [
18
- value.boolean("default or absent surface"),
19
- value.object({
20
- radius: { anyOf: [value.number("radius in pixels"), value.literal("full", "fully rounded radius")] },
21
- color: value.string("Appearance color role or CSS color"),
22
- material: {
23
- anyOf: [
24
- value.literal(false, "disabled Material"),
25
- value.object({
26
- grain: value.number("grain frequency"),
27
- grainAmount: value.number("grain intensity"),
28
- backdrop: value.number("backdrop blur"),
29
- opacity: value.number("Material opacity"),
30
- distortion: value.number("backdrop distortion"),
31
- saturation: value.number("backdrop saturation")
32
- }, [], "partial Appearance Material")
33
- ]
34
- }
35
- }, [], "Window surface customization")
36
- ]
37
- };
38
6
  const endpointDeclaration = value.nullable(value.object({
39
7
  start: value.boolean("whether a default Process starts this Endpoint"),
40
8
  service: value.boolean("default Service role for new execution contexts")
@@ -44,14 +12,12 @@ const clientDeclaration = value.nullable(value.object({
44
12
  service: value.boolean("default Service role for new execution contexts"),
45
13
  title: value.nullable(value.string("default Window title")),
46
14
  header: value.nullable(value.boolean("default Window header visibility")),
47
- surface: value.nullable(surface),
48
- transaction: value.nullable(transaction),
49
15
  size: value.nullable(value.object({ width: metric, height: metric }, ["width", "height"], "default Window size")),
50
16
  position: value.nullable(value.object({ x: metric, y: metric }, ["x", "y"], "default Window position")),
51
17
  layer: value.nullable(value.enumeration(layers, "default Window layer")),
52
18
  minimize: value.nullable(value.boolean("default minimized state")),
53
19
  maximize: value.nullable(value.boolean("default maximized state"))
54
- }, ["start", "service", "title", "header", "surface", "transaction", "size", "position", "layer", "minimize", "maximize"], "resolved Client Endpoint declaration"));
20
+ }, ["start", "service", "title", "header", "size", "position", "layer", "minimize", "maximize"], "resolved Client Endpoint declaration"));
55
21
  export const programOutput = value.object({
56
22
  identity: value.string("stable Program identity"),
57
23
  assetId: value.string("public Program asset identity"),
@@ -89,15 +55,13 @@ export const windowOutput = value.object({
89
55
  process: value.string("owning Process identity"),
90
56
  title: value.string("Window title"),
91
57
  header: value.boolean("whether the Desktop-owned Window header is shown"),
92
- surface,
93
- transaction,
94
58
  position: value.object({ x: metric, y: metric }, ["x", "y"], "Window position"),
95
59
  size: value.object({ width: metric, height: metric }, ["width", "height"], "Window size"),
96
60
  minimized: value.boolean("whether the Window is minimized"),
97
61
  maximized: value.boolean("whether the Window is maximized"),
98
62
  front: value.boolean("whether the Window is at the front of its layer"),
99
63
  layer: value.enumeration(layers, "Window layer")
100
- }, ["process", "title", "header", "surface", "transaction", "position", "size", "minimized", "maximized", "front", "layer"], "Window state");
64
+ }, ["process", "title", "header", "position", "size", "minimized", "maximized", "front", "layer"], "Window state");
101
65
  export const programPresentation = fields(["Identity", "identity"], ["Asset", "assetId"], ["Name", "name"], ["Version", "version"], ["Description", "description"], ["Installed", "installed"], ["Agent", "hasAgent"], ["Server", "server"], ["Client", "client"]);
102
66
  export const programListPresentation = list("data", "Program", "Programs", "No matching Programs", [
103
67
  { label: "Name", path: "name" },
@@ -123,7 +87,7 @@ export const serviceListPresentation = list("data", "Service", "Services", "No m
123
87
  { label: "Program", path: "program" },
124
88
  { label: "Endpoint", path: "endpoint" }
125
89
  ]);
126
- export const windowPresentation = fields(["Process", "process"], ["Title", "title"], ["Header", "header"], ["Surface", "surface"], ["Transaction", "transaction"], ["Position", "position"], ["Size", "size"], ["Minimized", "minimized"], ["Maximized", "maximized"], ["Front", "front"], ["Layer", "layer"]);
90
+ export const windowPresentation = fields(["Process", "process"], ["Title", "title"], ["Header", "header"], ["Position", "position"], ["Size", "size"], ["Minimized", "minimized"], ["Maximized", "maximized"], ["Front", "front"], ["Layer", "layer"]);
127
91
  export const windowPositionPresentation = fields(["Process", "process"], ["Position", "position"]);
128
92
  export const windowSizePresentation = fields(["Process", "process"], ["Size", "size"]);
129
93
  export const windowGeometryPresentation = fields(["Process", "process"], ["Position", "position"], ["Size", "size"]);
@@ -131,8 +95,6 @@ export const windowMinimizePresentation = fields(["Process", "process"], ["Minim
131
95
  export const windowMaximizePresentation = fields(["Process", "process"], ["Maximized", "maximized"]);
132
96
  export const windowTitlePresentation = fields(["Process", "process"], ["Title", "title"]);
133
97
  export const windowHeaderPresentation = fields(["Process", "process"], ["Header", "header"]);
134
- export const windowSurfacePresentation = fields(["Process", "process"], ["Surface", "surface"]);
135
- export const windowTransactionPresentation = fields(["Process", "process"], ["Transaction", "transaction"]);
136
98
  export const windowRaisePresentation = fields(["Process", "process"], ["Front", "front"]);
137
99
  export const eventPresentation = fields(["Scope", "scope"], ["Event", "event"], ["Payload", "payload"]);
138
100
  export const lifecyclePresentation = fields(["Scope", "scope"], ["Event", "event"]);
@@ -0,0 +1,32 @@
1
+ import { defineCommand } from "../contract/command.js";
2
+ import { value } from "../contract/schema.js";
3
+ import { connected } from "./connection.js";
4
+ import { executeDescription } from "./execution.js";
5
+ import { json } from "./input.js";
6
+ import { option, withJson } from "./options.js";
7
+ import { dataOutput } from "./schemas.js";
8
+ /** Add running-System capabilities to the System lifecycle command family. */
9
+ export default function systemAccessCommands(root, connect) {
10
+ const system = root.commands.find(command => command.name() === "system") ?? defineCommand(root, {
11
+ name: "system",
12
+ description: "access the running PhreshOS System"
13
+ });
14
+ defineCommand(system, {
15
+ name: "logs",
16
+ description: executeDescription("system", "logs"),
17
+ requiresSystem: true,
18
+ options: withJson(option("--statement <sql>", "read-only SQL statement", { mandatory: true }), option("--values <json>", "bound statement values encoded as a JSON array")),
19
+ output: dataOutput(value.array(value.any("log query row"), "log query rows"), "System log query result", { format: "value" }),
20
+ examples: ["phresh system logs --statement 'select createdAt, level, source, kind, content, data from logs order by createdAt desc limit 100' --json"]
21
+ }, ({ options }) => connected(connect, system => {
22
+ const parsed = options.values === undefined ? undefined : json(options.values, "--values");
23
+ if (parsed !== undefined && !Array.isArray(parsed))
24
+ throw new Error("--values must be a JSON array");
25
+ return system.execute({
26
+ $domain: "system",
27
+ $operation: "logs",
28
+ statement: options.statement,
29
+ ...(parsed === undefined ? {} : { values: parsed })
30
+ });
31
+ }));
32
+ }
@@ -1,7 +1,7 @@
1
- import { parseExecuteRequest, parseWindowSurface, parseWindowTransaction } from "@phreshos/core";
1
+ import { parseExecuteRequest } from "@phreshos/core";
2
2
  import { defineCommand } from "../contract/command.js";
3
3
  import { option, processOptions, timeoutOption, withJson } from "./options.js";
4
- import { dataOutput, eventOutput, eventPresentation, windowGeometryPresentation, windowSurfacePresentation, windowHeaderPresentation, windowMinimizePresentation, windowMaximizePresentation, windowOutput, windowPositionPresentation, windowTransactionPresentation, windowPresentation, windowRaisePresentation, windowSizePresentation, windowTitlePresentation } from "./schemas.js";
4
+ import { dataOutput, eventOutput, eventPresentation, windowGeometryPresentation, windowHeaderPresentation, windowMinimizePresentation, windowMaximizePresentation, windowOutput, windowPositionPresentation, windowPresentation, windowRaisePresentation, windowSizePresentation, windowTitlePresentation } from "./schemas.js";
5
5
  import { connected } from "./connection.js";
6
6
  import { bounded, position, size } from "./input.js";
7
7
  import { executeDescription } from "./execution.js";
@@ -56,27 +56,6 @@ export default function windowCommands(root, connect) {
56
56
  options: withJson(...processOptions, option("--hide", "hide rather than show the Window header")),
57
57
  examples: ["phresh window set-header --process main --program terminal --hide", "phresh window set-header --process main --program terminal"]
58
58
  }, async ({ options }) => executeWindow(connect, options, { $operation: "setHeader", header: options.hide !== true }));
59
- defineCommand(windows, {
60
- ...state("setSurface", windowSurfacePresentation),
61
- aliases: ["set-surface"],
62
- options: withJson(...processOptions, option("--default", "use the default Window surface"), option("--absent", "remove the Window surface"), option("--radius <radius>", "surface radius in pixels or full"), option("--color <color>", "Appearance color role or CSS color"), option("--without-material", "render the surface without Material"), option("--grain <value>", "surface Material grain", { parse: input => numeric(input, "--grain") }), option("--grain-amount <value>", "surface Material grain intensity", { parse: input => numeric(input, "--grain-amount") }), option("--backdrop <value>", "surface Material backdrop blur", { parse: input => numeric(input, "--backdrop") }), option("--opacity <value>", "surface Material opacity", { parse: input => numeric(input, "--opacity") }), option("--distortion <value>", "surface Material distortion", { parse: input => numeric(input, "--distortion") }), option("--saturation <value>", "surface Material saturation", { parse: input => numeric(input, "--saturation") })),
63
- examples: [
64
- "phresh window set-surface --process overlay --absent",
65
- "phresh window set-surface --process overlay --radius full --color primary"
66
- ]
67
- }, async ({ options }) => executeWindow(connect, options, { $operation: "setSurface", surface: surface(options) }));
68
- defineCommand(windows, {
69
- ...state("setTransaction", windowTransactionPresentation),
70
- aliases: ["set-transaction"],
71
- options: withJson(...processOptions, option("--default", "use the default Appearance transaction"), option("--disabled", "disable the default Window transaction"), option("--duration <milliseconds>", "transaction duration", { parse: input => numeric(input, "--duration") }), option("--easing <easing>", "standard easing name or four comma-separated cubic Bézier values")),
72
- examples: [
73
- "phresh window set-transaction --process overlay --default",
74
- "phresh window set-transaction --process overlay --duration 240 --easing ease-out"
75
- ]
76
- }, async ({ options }) => executeWindow(connect, options, {
77
- $operation: "setTransaction",
78
- transaction: transaction(options)
79
- }));
80
59
  defineCommand(windows, {
81
60
  ...state("raise", windowRaisePresentation),
82
61
  examples: ["phresh window raise --process main --program terminal"]
@@ -87,7 +66,7 @@ export default function windowCommands(root, connect) {
87
66
  requiresSystem: true,
88
67
  options: withJson(...processOptions, option("--event <event>", "Window event", {
89
68
  mandatory: true,
90
- choices: ["move", "resize", "minimize", "maximize", "changeTitle", "changeHeader", "changeSurface", "changeTransaction", "front"]
69
+ choices: ["move", "resize", "minimize", "maximize", "changeTitle", "changeHeader", "front"]
91
70
  }), timeoutOption),
92
71
  output: dataOutput(eventOutput("The observed Window event"), "One Window event", eventPresentation),
93
72
  examples: ["phresh window wait --process main --program terminal --event move --json"]
@@ -115,61 +94,3 @@ async function executeWindow(connect, options, operation) {
115
94
  });
116
95
  return connected(connect, system => system.execute(request));
117
96
  }
118
- function surface(options) {
119
- const materialValues = material(options);
120
- const customized = options.radius !== undefined || options.color !== undefined || materialValues !== undefined;
121
- const modes = Number(options.default === true) + Number(options.absent === true) + Number(customized);
122
- if (modes !== 1)
123
- throw new Error("Choose exactly one of --default, --absent, or surface customization options");
124
- if (options.default)
125
- return true;
126
- if (options.absent)
127
- return false;
128
- return parseWindowSurface({
129
- ...(options.radius === undefined ? {} : { radius: options.radius === "full" ? "full" : numeric(options.radius, "--radius") }),
130
- ...(options.color === undefined ? {} : { color: options.color }),
131
- ...(materialValues === undefined ? {} : { material: materialValues })
132
- });
133
- }
134
- function material(options) {
135
- const values = {
136
- grain: options.grain,
137
- grainAmount: options.grainAmount,
138
- backdrop: options.backdrop,
139
- opacity: options.opacity,
140
- distortion: options.distortion,
141
- saturation: options.saturation
142
- };
143
- const customized = Object.values(values).some(value => value !== undefined);
144
- const modes = Number(options.withoutMaterial === true) + Number(customized);
145
- if (modes > 1)
146
- throw new Error("Choose only one Material mode");
147
- if (options.withoutMaterial)
148
- return false;
149
- if (!customized)
150
- return undefined;
151
- return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined));
152
- }
153
- function transaction(options) {
154
- const customized = options.duration !== undefined || options.easing !== undefined;
155
- const modes = Number(options.default === true) + Number(options.disabled === true) + Number(customized);
156
- if (modes !== 1)
157
- throw new Error("Choose exactly one of --default, --disabled, or --duration");
158
- if (options.default)
159
- return true;
160
- if (options.disabled)
161
- return false;
162
- if (options.duration === undefined)
163
- throw new Error("--easing requires --duration");
164
- if (options.easing === undefined)
165
- return parseWindowTransaction(options.duration);
166
- const pieces = options.easing.split(",").map(value => value.trim());
167
- const easing = pieces.length === 4 ? pieces.map(value => numeric(value, "--easing")) : options.easing;
168
- return parseWindowTransaction({ duration: options.duration, easing });
169
- }
170
- function numeric(value, name) {
171
- const result = Number(value);
172
- if (!Number.isFinite(result))
173
- throw new Error(`${name} must be a finite number`);
174
- return result;
175
- }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "phresh",
3
3
  "private": true,
4
- "version": "0.1.42",
4
+ "version": "0.1.44",
5
5
  "description": "The official PhreshOS starter Program.",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -14,15 +14,15 @@
14
14
  "starter"
15
15
  ],
16
16
  "dependencies": {
17
- "@phreshos/client": "^0.1.48",
18
- "@phreshos/core": "^0.1.56",
19
- "@phreshos/react": "^0.1.29",
20
- "@phreshos/server": "^0.1.52",
17
+ "@phreshos/client": "^0.1.50",
18
+ "@phreshos/core": "^0.1.59",
19
+ "@phreshos/react": "^0.1.31",
20
+ "@phreshos/server": "^0.1.55",
21
21
  "react": "^19.2.8",
22
22
  "react-dom": "^19.2.8"
23
23
  },
24
24
  "devDependencies": {
25
- "@phreshos/cli": "^0.1.69",
25
+ "@phreshos/cli": "^0.1.71",
26
26
  "@types/node": "^26.4.0",
27
27
  "@types/react": "^19.2.18",
28
28
  "@types/react-dom": "^19.2.5",
@@ -4,7 +4,7 @@ export default defineConfig({
4
4
  identity: "phresh",
5
5
  name: "Phresh Program",
6
6
  description: "A minimal counter with direct Client and Server endpoints.",
7
- version: "0.1.42",
7
+ version: "0.1.44",
8
8
  icon: "icon.png",
9
9
  categories: ["Development"],
10
10
  keywords: ["example", "counter", "client", "server"],
@@ -7,7 +7,9 @@ export default defineConfig({
7
7
  plugins: [react()],
8
8
  base: process.env.PHRESHOS_CLIENT_BASE ?? "./",
9
9
  resolve: {
10
- tsconfigPaths: true
10
+ tsconfigPaths: true,
11
+ // Linked SDKs must consume the Program's renderer instance.
12
+ dedupe: ["react", "react-dom"]
11
13
  },
12
14
  server: {
13
15
  port: Number(process.env.PHRESHOS_CLIENT_PORT ?? "5200"),
@@ -1,6 +1,7 @@
1
1
  import { defineConfig } from "vitest/config"
2
2
 
3
3
  export default defineConfig({
4
+ resolve: { dedupe: ["react", "react-dom"] },
4
5
  test: {
5
6
  pool: "forks",
6
7
  maxWorkers: 2,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "repository": "PhreshOS/phresh-program",
3
- "version": "0.1.42",
4
- "sha256": "a05d624c773f52acaf7b16f65b0fd8f421bf61e7caad84348e4ec3871ae019cd",
3
+ "version": "0.1.44",
4
+ "sha256": "5d218afff54104c06bb8e279247f875ccbc68b7ce789b4207da8af3428946c39",
5
5
  "development": true
6
6
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@phreshos/cli",
3
3
  "type": "module",
4
- "version": "0.1.69",
4
+ "version": "0.1.71",
5
5
  "description": "The Phresh command-line interface for Program projects and system management.",
6
6
  "engines": {
7
7
  "node": ">=20.10"
@@ -47,8 +47,8 @@
47
47
  "packageManager": "bun@1.3.14",
48
48
  "dependencies": {
49
49
  "@clack/prompts": "^1.7.0",
50
- "@phreshos/core": "^0.1.58",
51
- "@phreshos/node": "^0.1.31",
50
+ "@phreshos/core": "^0.1.60",
51
+ "@phreshos/node": "^0.1.33",
52
52
  "adm-zip": "^0.6.0",
53
53
  "commander": "^15.0.0",
54
54
  "picocolors": "^1.1.1"