pinokiod 7.3.0 → 7.3.3

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.
Files changed (125) hide show
  1. package/kernel/api/github/index.js +444 -0
  2. package/kernel/api/index.js +199 -11
  3. package/kernel/api/process/index.js +124 -44
  4. package/kernel/api/shell_run_template.js +273 -0
  5. package/kernel/api/uri/index.js +51 -0
  6. package/kernel/bin/{conda-python.js → conda-pins.js} +23 -0
  7. package/kernel/bin/conda.js +15 -5
  8. package/kernel/bin/git.js +9 -10
  9. package/kernel/bin/huggingface.js +1 -1
  10. package/kernel/bin/index.js +5 -2
  11. package/kernel/bin/zip.js +9 -1
  12. package/kernel/connect/providers/github/README.md +5 -4
  13. package/kernel/environment.js +195 -92
  14. package/kernel/git.js +98 -19
  15. package/kernel/gitconfig_template +7 -0
  16. package/kernel/gpu/amd.js +72 -0
  17. package/kernel/gpu/apple.js +8 -0
  18. package/kernel/gpu/common.js +12 -0
  19. package/kernel/gpu/intel.js +47 -0
  20. package/kernel/gpu/nvidia.js +8 -0
  21. package/kernel/index.js +11 -1
  22. package/kernel/managed_skills.js +871 -0
  23. package/kernel/plugin.js +6 -58
  24. package/kernel/plugin_sources.js +316 -0
  25. package/kernel/resource_usage/gpu.js +349 -0
  26. package/kernel/resource_usage/index.js +322 -0
  27. package/kernel/resource_usage/macos_footprint.js +197 -0
  28. package/kernel/resource_usage/preferences.js +92 -0
  29. package/kernel/resource_usage/process_tree.js +303 -0
  30. package/kernel/scripts/git/create +4 -4
  31. package/kernel/scripts/git/fork +7 -8
  32. package/kernel/shell.js +23 -2
  33. package/kernel/shells.js +41 -0
  34. package/kernel/sysinfo.js +62 -9
  35. package/kernel/util.js +60 -0
  36. package/package.json +1 -1
  37. package/server/index.js +984 -156
  38. package/server/lib/app_log_report.js +543 -0
  39. package/server/lib/content_validation.js +55 -33
  40. package/server/lib/launcher_instruction_bootstrap.js +4 -96
  41. package/server/lib/terminal_session_helpers.js +0 -3
  42. package/server/public/common.js +77 -31
  43. package/server/public/create-launcher.js +4 -32
  44. package/server/public/logs.js +1428 -0
  45. package/server/public/nav.js +7 -0
  46. package/server/public/plugin-detail.js +93 -10
  47. package/server/public/privacy_filter_worker.js +391 -0
  48. package/server/public/style.css +1104 -154
  49. package/server/public/task-launcher.js +8 -29
  50. package/server/public/universal-launcher.css +8 -6
  51. package/server/public/universal-launcher.js +3 -27
  52. package/server/routes/apps.js +195 -1
  53. package/server/views/app.ejs +3041 -717
  54. package/server/views/autolaunch.ejs +917 -0
  55. package/server/views/bootstrap.ejs +7 -1
  56. package/server/views/d.ejs +408 -65
  57. package/server/views/editor.ejs +85 -19
  58. package/server/views/index.ejs +661 -111
  59. package/server/views/init/index.ejs +1 -1
  60. package/server/views/install.ejs +1 -1
  61. package/server/views/logs.ejs +164 -86
  62. package/server/views/net.ejs +7 -1
  63. package/server/views/partials/d_terminal_column.ejs +2 -2
  64. package/server/views/partials/d_terminal_options.ejs +0 -8
  65. package/server/views/partials/fs_status.ejs +47 -0
  66. package/server/views/partials/home_action_modal.ejs +86 -0
  67. package/server/views/partials/home_run_menu.ejs +87 -0
  68. package/server/views/partials/main_sidebar.ejs +2 -0
  69. package/server/views/partials/menu.ejs +1 -1
  70. package/server/views/plugin_detail.ejs +19 -4
  71. package/server/views/plugins.ejs +201 -3
  72. package/server/views/pre.ejs +1 -1
  73. package/server/views/pro.ejs +1 -1
  74. package/server/views/shell.ejs +40 -18
  75. package/server/views/skills.ejs +506 -0
  76. package/server/views/terminal.ejs +45 -19
  77. package/spec/INSTRUCTION_SYNC.md +20 -10
  78. package/system/plugin/antigravity-cli/antigravity.png +0 -0
  79. package/system/plugin/antigravity-cli/common.js +155 -0
  80. package/system/plugin/antigravity-cli/install.js +272 -0
  81. package/system/plugin/antigravity-cli/pinokio.js +13 -0
  82. package/system/plugin/antigravity-cli-auto/antigravity.png +0 -0
  83. package/system/plugin/antigravity-cli-auto/pinokio.js +13 -0
  84. package/system/plugin/claude/claude.png +0 -0
  85. package/system/plugin/claude/pinokio.js +47 -0
  86. package/system/plugin/claude-auto/claude.png +0 -0
  87. package/system/plugin/claude-auto/pinokio.js +58 -0
  88. package/system/plugin/claude-desktop/icon.jpeg +0 -0
  89. package/system/plugin/claude-desktop/pinokio.js +23 -0
  90. package/system/plugin/codex/openai.webp +0 -0
  91. package/system/plugin/codex/pinokio.js +42 -0
  92. package/system/plugin/codex-auto/openai.webp +0 -0
  93. package/system/plugin/codex-auto/pinokio.js +49 -0
  94. package/system/plugin/codex-desktop/icon.png +0 -0
  95. package/system/plugin/codex-desktop/pinokio.js +23 -0
  96. package/system/plugin/crush/crush.png +0 -0
  97. package/system/plugin/crush/pinokio.js +15 -0
  98. package/system/plugin/cursor/cursor.jpeg +0 -0
  99. package/system/plugin/cursor/pinokio.js +23 -0
  100. package/system/plugin/qwen/pinokio.js +34 -0
  101. package/system/plugin/qwen/qwen.png +0 -0
  102. package/system/plugin/vscode/pinokio.js +20 -0
  103. package/system/plugin/vscode/vscode.png +0 -0
  104. package/system/plugin/windsurf/pinokio.js +23 -0
  105. package/system/plugin/windsurf/windsurf.png +0 -0
  106. package/test/antigravity-cli-plugin.test.js +185 -0
  107. package/test/app-api.test.js +239 -0
  108. package/test/app-log-report.test.js +67 -0
  109. package/test/environment-cache-preflight.test.js +98 -0
  110. package/test/git-bin.test.js +59 -0
  111. package/test/git-defaults.test.js +97 -0
  112. package/test/github-api.test.js +158 -0
  113. package/test/github-connection.test.js +117 -0
  114. package/test/huggingface-bin.test.js +25 -0
  115. package/test/managed-skills.test.js +351 -0
  116. package/test/plugin-action-functions.test.js +337 -0
  117. package/test/plugin-dev-iframe.test.js +17 -0
  118. package/test/plugin-sources.test.js +203 -0
  119. package/test/privacy-filter-worker-heuristics.test.js +69 -0
  120. package/test/process-wait.test.js +169 -0
  121. package/test/script-api.test.js +97 -0
  122. package/test/shell-api.test.js +134 -0
  123. package/test/shell-run-template.test.js +209 -0
  124. package/test/storage-api.test.js +137 -0
  125. package/test/uri-api.test.js +100 -0
@@ -0,0 +1,209 @@
1
+ const assert = require('node:assert/strict')
2
+ const fs = require('node:fs/promises')
3
+ const os = require('node:os')
4
+ const path = require('node:path')
5
+ const test = require('node:test')
6
+
7
+ const ShellRunTemplate = require('../kernel/api/shell_run_template')
8
+ const Shell = require('../kernel/shell')
9
+
10
+ function createKernel(root = process.cwd()) {
11
+ return {
12
+ homedir: root,
13
+ bracketedPasteSupport: {},
14
+ connect: {
15
+ keys: async () => null
16
+ },
17
+ envs: process.env,
18
+ exists: async (filepath) => {
19
+ try {
20
+ await fs.access(filepath)
21
+ return true
22
+ } catch (_) {
23
+ return false
24
+ }
25
+ },
26
+ path: (type, ...parts) => path.join(root, type, ...parts)
27
+ }
28
+ }
29
+
30
+ function createShell(kernel = createKernel()) {
31
+ return new Shell(kernel)
32
+ }
33
+
34
+ test('renderEnvArgs protects multiline structured shell.run argv values', () => {
35
+ const rpc = {
36
+ method: 'shell.run',
37
+ params: {
38
+ shell: 'bash',
39
+ message: {
40
+ _: ['python', '-c', 'print("a")\nprint("b")']
41
+ },
42
+ env: {
43
+ EXISTING: '1'
44
+ }
45
+ }
46
+ }
47
+
48
+ const rendered = ShellRunTemplate.renderEnvArgs({ platform: 'darwin' }, rpc, {})
49
+
50
+ assert.notStrictEqual(rendered, rpc)
51
+ assert.deepEqual(rendered.params.message, {
52
+ _: ['python', '-c', '__PINOKIO_ENVARG_0__']
53
+ })
54
+ assert.equal(rendered.params.env.EXISTING, '1')
55
+ assert.equal(rendered.params.env.PINOKIO_ARG_0, 'print("a")\nprint("b")')
56
+ assert.deepEqual(rendered.params._pinokio_env_args, [
57
+ {
58
+ name: 'PINOKIO_ARG_0',
59
+ value: 'print("a")\nprint("b")'
60
+ }
61
+ ])
62
+ assert.equal(rendered.params._pinokio_cmd_delayed_expansion, false)
63
+ })
64
+
65
+ test('renderEnvArgs is a no-op for non-multiline or raw string shell.run messages', () => {
66
+ const structured = {
67
+ method: 'shell.run',
68
+ params: {
69
+ message: {
70
+ _: ['echo', 'hello']
71
+ }
72
+ }
73
+ }
74
+ const rawString = {
75
+ method: 'shell.run',
76
+ params: {
77
+ message: 'echo one\necho two'
78
+ }
79
+ }
80
+ const differentMethod = {
81
+ method: 'fs.write',
82
+ params: {
83
+ message: {
84
+ _: ['echo', 'one\ntwo']
85
+ }
86
+ }
87
+ }
88
+
89
+ assert.strictEqual(ShellRunTemplate.renderEnvArgs({ platform: 'darwin' }, structured, {}), structured)
90
+ assert.strictEqual(ShellRunTemplate.renderEnvArgs({ platform: 'darwin' }, rawString, {}), rawString)
91
+ assert.strictEqual(ShellRunTemplate.renderEnvArgs({ platform: 'darwin' }, differentMethod, {}), differentMethod)
92
+ })
93
+
94
+ test('renderEnvArgs marks cmd shell runs for delayed expansion', () => {
95
+ const rpc = {
96
+ method: 'shell.run',
97
+ params: {
98
+ shell: 'cmd.exe',
99
+ message: {
100
+ _: ['node', '-e', 'console.log("a")\nconsole.log("b")']
101
+ }
102
+ }
103
+ }
104
+
105
+ const rendered = ShellRunTemplate.renderEnvArgs({ platform: 'win32' }, rpc, {})
106
+
107
+ assert.equal(rendered.params._pinokio_cmd_delayed_expansion, true)
108
+ assert.equal(rendered.params.env.PINOKIO_ARG_0, 'console.log("a")\nconsole.log("b")')
109
+ })
110
+
111
+ test('Shell.buildStructuredMessage expands env arg markers with shell-specific quoting', () => {
112
+ const shell = createShell()
113
+ const message = {
114
+ _: ['python', '-c', '__PINOKIO_ENVARG_0__']
115
+ }
116
+
117
+ assert.equal(
118
+ shell.buildStructuredMessage(message, 'bash'),
119
+ '\'python\' \'-c\' "$PINOKIO_ARG_0"'
120
+ )
121
+ assert.equal(
122
+ shell.buildStructuredMessage(message, 'powershell'),
123
+ '& \'python\' \'-c\' "${env:PINOKIO_ARG_0}"'
124
+ )
125
+ assert.equal(
126
+ shell.buildStructuredMessage(message, 'cmd.exe'),
127
+ '"python" "-c" "!PINOKIO_ARG_0!"'
128
+ )
129
+ })
130
+
131
+ test('Shell.init_env preserves multiline Pinokio argv env values only', async () => {
132
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-shell-envarg-'))
133
+ await fs.mkdir(path.join(root, 'api'), { recursive: true })
134
+ await fs.writeFile(path.join(root, 'ENVIRONMENT'), 'PINOKIO_TEST_ENV=1\n')
135
+ const shell = createShell(createKernel(root))
136
+
137
+ await shell.init_env({
138
+ path: process.cwd(),
139
+ env: {
140
+ PINOKIO_ARG_0: 'line one\nline two',
141
+ OTHER_MULTILINE: 'line one\nline two'
142
+ }
143
+ })
144
+
145
+ assert.equal(shell.env.PINOKIO_ARG_0, 'line one\nline two')
146
+ assert.equal(shell.env.OTHER_MULTILINE, 'line one line two')
147
+ })
148
+
149
+ test('Shell.init_env disables Hugging Face hub update checks by default without overriding apps', async () => {
150
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-shell-hf-env-'))
151
+ await fs.mkdir(path.join(root, 'api'), { recursive: true })
152
+ await fs.writeFile(path.join(root, 'ENVIRONMENT'), 'PINOKIO_TEST_ENV=1\n')
153
+
154
+ const defaultShell = createShell(createKernel(root))
155
+ await defaultShell.init_env({
156
+ path: process.cwd(),
157
+ env: {}
158
+ })
159
+ assert.equal(defaultShell.env.HF_HUB_DISABLE_UPDATE_CHECK, '1')
160
+
161
+ const overrideShell = createShell(createKernel(root))
162
+ await overrideShell.init_env({
163
+ path: process.cwd(),
164
+ env: {
165
+ HF_HUB_DISABLE_UPDATE_CHECK: '0'
166
+ }
167
+ })
168
+ assert.equal(overrideShell.env.HF_HUB_DISABLE_UPDATE_CHECK, '0')
169
+ })
170
+
171
+ test('Shell.init_env keeps Windows Hugging Face symlink defaults scoped to win32', async () => {
172
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-shell-hf-win-'))
173
+ await fs.mkdir(path.join(root, 'api'), { recursive: true })
174
+ await fs.writeFile(path.join(root, 'ENVIRONMENT'), 'PINOKIO_TEST_ENV=1\n')
175
+
176
+ const darwinShell = createShell(createKernel(root))
177
+ darwinShell.platform = 'darwin'
178
+ await darwinShell.init_env({
179
+ path: process.cwd(),
180
+ env: {}
181
+ })
182
+ assert.equal(darwinShell.env.HF_HUB_DISABLE_UPDATE_CHECK, '1')
183
+ assert.equal(darwinShell.env.HF_HUB_DISABLE_SYMLINKS, undefined)
184
+
185
+ const winShell = createShell(createKernel(root))
186
+ winShell.platform = 'win32'
187
+ await winShell.init_env({
188
+ path: process.cwd(),
189
+ env: {}
190
+ })
191
+ assert.equal(winShell.env.HF_HUB_DISABLE_UPDATE_CHECK, '1')
192
+ assert.equal(winShell.env.HF_HUB_DISABLE_SYMLINKS, '1')
193
+ assert.equal(winShell.env.HF_HUB_DISABLE_SYMLINKS_WARNING, '1')
194
+ })
195
+
196
+ test('redactEnvArgs summarizes protected argv env values', () => {
197
+ const redacted = ShellRunTemplate.redactEnvArgs({
198
+ PINOKIO_ARG_0: 'line one\nline two',
199
+ REGULAR_VALUE: 'visible'
200
+ })
201
+
202
+ assert.equal(redacted.REGULAR_VALUE, 'visible')
203
+ assert.deepEqual(redacted.PINOKIO_ARG_0, {
204
+ type: 'pinokio env arg',
205
+ lines: 2,
206
+ preview: 'line one\nline two',
207
+ truncated: false
208
+ })
209
+ })
@@ -0,0 +1,137 @@
1
+ const test = require('node:test')
2
+ const assert = require('node:assert/strict')
3
+ const fs = require('node:fs/promises')
4
+ const os = require('node:os')
5
+ const path = require('node:path')
6
+ const Loader = require('../kernel/loader')
7
+ const setApi = require('../kernel/api/set')
8
+ const rmApi = require('../kernel/api/rm')
9
+ const SelfAPI = require('../kernel/api/self')
10
+
11
+ function createKernel () {
12
+ return {
13
+ memory: {
14
+ local: {},
15
+ global: {}
16
+ },
17
+ loader: new Loader()
18
+ }
19
+ }
20
+
21
+ test('generic set and rm update local/global memory and self JSON files', async () => {
22
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-storage-api-'))
23
+ const kernel = createKernel()
24
+ const parent = {
25
+ id: 'request-1',
26
+ path: path.join(root, 'script.js')
27
+ }
28
+
29
+ try {
30
+ await setApi({
31
+ parent,
32
+ cwd: root,
33
+ params: {
34
+ local: {
35
+ 'nested.value': 42,
36
+ items: ['a', 'b', 'c']
37
+ },
38
+ global: {
39
+ 'state.ready': true
40
+ },
41
+ self: {
42
+ 'data/state.json': {
43
+ 'nested.keep': 'yes',
44
+ 'nested.drop': 'no',
45
+ items: ['x', 'y', 'z']
46
+ }
47
+ }
48
+ }
49
+ }, () => {}, kernel)
50
+
51
+ assert.deepEqual(kernel.memory.local[parent.id], {
52
+ nested: { value: 42 },
53
+ items: ['a', 'b', 'c']
54
+ })
55
+ assert.deepEqual(kernel.memory.global[parent.id], {
56
+ state: { ready: true }
57
+ })
58
+
59
+ await rmApi({
60
+ parent,
61
+ cwd: root,
62
+ params: {
63
+ local: ['nested.value'],
64
+ global: ['state.ready'],
65
+ self: {
66
+ 'data/state.json': ['nested.drop', 'items.1']
67
+ }
68
+ }
69
+ }, () => {}, kernel)
70
+
71
+ assert.deepEqual(kernel.memory.local[parent.id], {
72
+ nested: {},
73
+ items: ['a', 'b', 'c']
74
+ })
75
+ assert.deepEqual(kernel.memory.global[parent.id], {
76
+ state: {}
77
+ })
78
+ assert.deepEqual(
79
+ JSON.parse(await fs.readFile(path.join(root, 'data/state.json'), 'utf8')),
80
+ {
81
+ nested: { keep: 'yes' },
82
+ items: ['x', 'z']
83
+ }
84
+ )
85
+ } finally {
86
+ await fs.rm(root, { recursive: true, force: true })
87
+ }
88
+ })
89
+
90
+ test('self.set and self.rm wrap JSON file mutation without touching real launchers', async () => {
91
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'pinokio-self-api-'))
92
+ const kernel = createKernel()
93
+ const selfApi = new SelfAPI()
94
+ const parent = {
95
+ id: 'request-2',
96
+ path: path.join(root, 'script.js')
97
+ }
98
+
99
+ try {
100
+ await selfApi.set({
101
+ parent,
102
+ cwd: root,
103
+ params: {
104
+ 'pinokio.json': {
105
+ title: 'Temporary launcher',
106
+ 'plugin.menu': ['Run']
107
+ }
108
+ }
109
+ }, () => {}, kernel)
110
+
111
+ assert.deepEqual(
112
+ JSON.parse(await fs.readFile(path.join(root, 'pinokio.json'), 'utf8')),
113
+ {
114
+ title: 'Temporary launcher',
115
+ plugin: { menu: ['Run'] }
116
+ }
117
+ )
118
+
119
+ await selfApi.rm({
120
+ parent,
121
+ cwd: root,
122
+ params: {
123
+ 'pinokio.json': ['plugin.menu']
124
+ }
125
+ }, () => {}, kernel)
126
+
127
+ assert.deepEqual(
128
+ JSON.parse(await fs.readFile(path.join(root, 'pinokio.json'), 'utf8')),
129
+ {
130
+ title: 'Temporary launcher',
131
+ plugin: {}
132
+ }
133
+ )
134
+ } finally {
135
+ await fs.rm(root, { recursive: true, force: true })
136
+ }
137
+ })
@@ -0,0 +1,100 @@
1
+ const assert = require('node:assert/strict')
2
+ const test = require('node:test')
3
+
4
+ const URI = require('../kernel/api/uri')
5
+ const Util = require('../kernel/util')
6
+
7
+ test('uri.open builds URIs with query params without corrupting schemes', () => {
8
+ const api = new URI()
9
+
10
+ assert.equal(
11
+ api.build({ uri: 'https://example.test/path' }),
12
+ 'https://example.test/path'
13
+ )
14
+ assert.equal(
15
+ api.build({
16
+ uri: 'https://example.test/path',
17
+ params: {
18
+ q: 'hello world',
19
+ tag: ['one', 'two'],
20
+ meta: { nested: true },
21
+ skip: null
22
+ }
23
+ }),
24
+ 'https://example.test/path?q=hello%20world&tag=one&tag=two&meta=%7B%22nested%22%3Atrue%7D'
25
+ )
26
+ assert.equal(
27
+ api.build({
28
+ uri: 'https://example.test/path#section',
29
+ params: { q: 'x' }
30
+ }),
31
+ 'https://example.test/path?q=x#section'
32
+ )
33
+ assert.equal(
34
+ api.build({
35
+ uri: 'vscode://file/tmp/test.js',
36
+ params: { line: 12 }
37
+ }),
38
+ 'vscode://file/tmp/test.js?line=12'
39
+ )
40
+ assert.equal(
41
+ api.build({
42
+ uri: 'cursor://file/tmp/test.js',
43
+ params: { line: 12 }
44
+ }),
45
+ 'cursor://file/tmp/test.js?line=12'
46
+ )
47
+ assert.equal(
48
+ api.build({
49
+ uri: 'obsidian://open?vault=test',
50
+ params: { file: 'Daily Note' }
51
+ }),
52
+ 'obsidian://open?vault=test&file=Daily%20Note'
53
+ )
54
+ assert.equal(
55
+ api.build({
56
+ uri: 'mailto:test@example.com',
57
+ params: { subject: 'Pinokio test' }
58
+ }),
59
+ 'mailto:test@example.com?subject=Pinokio%20test'
60
+ )
61
+ assert.equal(
62
+ api.build({ uri: 'file:///tmp/pinokio-uri-open-test.txt' }),
63
+ 'file:///tmp/pinokio-uri-open-test.txt'
64
+ )
65
+ assert.throws(
66
+ () => api.build({}),
67
+ /uri\.open requires params\.uri/
68
+ )
69
+ })
70
+
71
+ test('uri.open dispatches the exact built URI to Util.openURI', async () => {
72
+ const api = new URI()
73
+ const originalOpenURI = Util.openURI
74
+ const opened = []
75
+
76
+ Util.openURI = async (uri) => {
77
+ opened.push(uri)
78
+ return { ok: true, status: 'stubbed' }
79
+ }
80
+
81
+ try {
82
+ const response = await api.open({
83
+ params: {
84
+ uri: 'cursor://file/tmp/test.js',
85
+ params: {
86
+ line: 42,
87
+ column: 7
88
+ }
89
+ }
90
+ }, () => {})
91
+
92
+ assert.deepEqual(opened, ['cursor://file/tmp/test.js?line=42&column=7'])
93
+ assert.deepEqual(response, {
94
+ uri: 'cursor://file/tmp/test.js?line=42&column=7',
95
+ result: { ok: true, status: 'stubbed' }
96
+ })
97
+ } finally {
98
+ Util.openURI = originalOpenURI
99
+ }
100
+ })